问题
I've been searching for a few days on how to improve a program I wrote for work. The program, which uses python 3.6, simply sends pre-formatted .doc files to the printer, but I can't seem to find a way on how to signal the function to stop sending the file to print once the printer has run out of paper. The number of documents printed varies, so I can't just use a simple range function.
I've looked into the win32print module and the pycups module (which won't pip install not matter what I try). Is there something in the signal module that captures external error messages from other apps? Ideally, what would be great, is if the python script could check the status of the print queue first, before sending the file.
I found that the code below, using the win32print module, that should accomplish this, but it doesn't seem to work.
import win32print
p = win32print.OpenPrinter("Canon Inkjet iP1800 series")
raw = win32print.EnumJobs(p, 0, 999)
def main():
while len(raw) > 0:
#does some function
if #receives error from printer:
break
main()
win32print.ClosePrinter(p)
回答1:
Side note: I must say that pywin32 is Win based, while pycups (or any cups wrapper) is Ux based so, unless there's some cups port for Win that I'm not aware of, you should pick one of the above 2 (preferably, matching the platform/arch that you're on).
I've done some research, and it's not necessary to iterate trough all the printer jobs, in order to check whether the printer is in an erroneous state. Also, looping over jobs from 0 to 999, doesn't guarantee that all jobs are checked, so the logic above (even if it was correct - which is not) would not stand.
Here's a sample implementation (I took the liberty of adding more errors than specified in the question: running out of paper(win32print.PRINTER_STATUS_PAPER_OUT
) and placed them in
PRINTER_ERROR_STATES
(comment out the ones that you don't see as errors):
import win32print
PRINTER_ERROR_STATES = (
win32print.PRINTER_STATUS_NO_TONER,
win32print.PRINTER_STATUS_NOT_AVAILABLE,
win32print.PRINTER_STATUS_OFFLINE,
win32print.PRINTER_STATUS_OUT_OF_MEMORY,
win32print.PRINTER_STATUS_OUTPUT_BIN_FULL,
win32print.PRINTER_STATUS_PAGE_PUNT,
win32print.PRINTER_STATUS_PAPER_JAM,
win32print.PRINTER_STATUS_PAPER_OUT,
win32print.PRINTER_STATUS_PAPER_PROBLEM,
)
def printer_errorneous_state(printer, error_states=PRINTER_ERROR_STATES):
prn_opts = win32print.GetPrinter(printer)
status_opts = prn_opts[18]
for error_state in error_states:
if status_opts & error_state:
return error_state
return 0
def main():
printer_name = "Canon Inkjet iP1800 series" # or get_printer_names()[0]
prn = win32print.OpenPrinter(printer_name)
error = printer_errorneous_state(prn)
if error:
print("ERROR occurred: ", error)
else:
print("Printer OK...")
# Do the real work
win32print.ClosePrinter(prn)
if __name__ == "__main__":
main()
Note: Apparently, Win doesn't store the printer names as set on printers. In my case, I have a printer called EPSON******. However in Win, its name is EPSON****** (WF-7610 Series). That's why I had to write some additional code (that I didn't include here) to enumerate all available printers and get their names.
来源:https://stackoverflow.com/questions/42726925/python-how-to-communicate-with-printer