Python打印宏在部分HP激光打印机上静默取消任务的排查求助
Python打印宏在部分HP激光打印机上静默取消任务的排查求助
大家好,我最近开发了一个Python打印宏,核心功能是把信头粘贴到PDF文档上,再发送到打印机完成打印。这个工具在大部分公司部署后都运行正常,但在部分HP激光打印机上遇到了棘手的问题:打印任务能正常出现在打印机队列中,但很快就会被静默取消,完全没有输出。
已排查的信息:
- 最初怀疑是老型号打印机内存不足,所以把PDF转位图的DPI从300降到了150,但问题依然存在
- 测试环境(正常):HP LaserJet M608
- 出问题的机型:HP LaserJet 600 M601
- 同时该宏也会向HP LaserJet 600 M603发送任务(暂时未反馈问题)
- 程序通过PyInstaller打包为可执行文件分发
- 使用的依赖库:
sys、os、json、win32print、win32ui、win32con、win32gui、fitz、shutil、logging、uuid、PIL、pypdf
关键代码片段:
1. PDF转位图的函数
def convert_to_bitmap(pdf_path, input_name): print_queue = [] # cycle through pages in doc for bitmap conversions doc = fitz.open(pdf_path) i = 0 logger.info("Converting PDF file pages to bitmaps") for page in doc: pixmap = page.get_pixmap(dpi=150) # convert page to pixel map img = Image.frombytes("RGB", [pixmap.width, pixmap.height], pixmap.samples) # converts pixel map to PIL image # creates appropriate path and saves bit map uuid4 = uuid.uuid4() bitmap_name = f"bitmap({i})-" + str(uuid4) + ".bmp" bitmap_path = get_resource_path(f"temp\\{bitmap_name}") try: img.save(bitmap_path) except PermissionError as e: logger.error(f"User lacks permission to save bitmap to {bitmap_path}:\n{e} \nExiting program") input_path = get_resource_path(os.path.join("temp\\", input_name)) clean_up(print_queue, input_path, pdf_path) sys.exit(1) except FileNotFoundError as e: logger.error(f"{bitmap_path} is an invalid directory:\n{e} \nExiting program") input_path = get_resource_path(os.path.join("temp\\", input_name)) clean_up(print_queue, input_path, pdf_path) sys.exit(1) except ValueError as e: logger.error(f"Unsupported file format or specifier:\n{e} \nExiting program") input_path = get_resource_path(os.path.join("temp\\", input_name)) clean_up(print_queue, input_path, pdf_path) sys.exit(1) except OSError as e: logger.error(f"OS error encountered:\n{e} \nExiting program") input_path = get_resource_path(os.path.join("temp\\", input_name)) clean_up(print_queue, input_path, pdf_path) sys.exit(1) except Exception as e: logger.error(f"Unexpected error encountered:\n{e} \nExiting program") input_path = get_resource_path(os.path.join("temp\\", input_name)) clean_up(print_queue, input_path, pdf_path) sys.exit(1) print_queue.append(bitmap_path) # queues up bitmap for printing i = i + 1 logger.info(f"Page {i + 1}: converted to bitmap") logger.info("All PDF file pages converted to bitmaps") return print_queue
2. 发送打印任务的函数(关键部分)
def print_pdf(printer, tray, print_queue): # cycle through printers to see if passed printer is valid printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS) valid_printer = False for p in printers: if (p[2] == printer): valid_printer = True logger.info(f"Printer: {printer} found") if (not(valid_printer)): # printer not found setting to default logger.warning(f"Printer: {printer} not found") printer = win32print.GetDefaultPrinter() logger.info(f"Printing from default: {printer}") # creates handler, device context, memory device context, and starts print job printer_handler = win32print.OpenPrinter(printer) # acceses printer settings devmode = win32print.GetPrinter(printer_handler, 2)["pDevMode"] if tray is not None: # sets tray if tray >= 0 if tray >= 0: devmode.DefaultSource = tray logger.info(f"Tray set to: {tray}") else: logger.warning(f"Tray set to default: {devmode.DefaultSource}") win32print.DocumentProperties(0, printer_handler, printer, devmode, devmode, win32con.DM_IN_BUFFER | win32con.DM_OUT_BUFFER) dc = win32ui.CreateDC() dc.CreatePrinterDC(printer) memory_dc = dc.CreateCompatibleDC() dc.StartDoc("Letterhead on Message") # gets page dimensions page_width = dc.GetDeviceCaps(win32con.HORZRES) page_height = dc.GetDeviceCaps(win32con.VERTRES) # cycles bitmaps for each page for bm in print_queue: dc.StartPage() # load bitmap object bitmap_handle = win32gui.LoadImage(0, bm, win32con.IMAGE_BITMAP, 0, 0, win32con.LR_LOADFROMFILE) bitmap = win32ui.CreateBitmapFromHandle(bitmap_handle) old_bitmap = memory_dc.SelectObject(bitmap) # 原代码此处有截断,以下为现有完整部分 bitmap_info = bitmap.GetInfo() # 后续绘制逻辑(原代码未完全提供) # ...
想请教大家的问题:
- 有没有遇到过HP LaserJet 600 M601这类老机型和Python打印库的兼容性问题?
- PDF转位图的过程中,有没有什么细节(比如位图格式、颜色模式)会导致老打印机无法识别?
- 使用
win32print系列库配置打印参数时,针对这类机型有没有特殊的设置项需要注意? - 有没有可能是PyInstaller打包后的exe在某些系统上存在权限或依赖缺失的问题?
内容来源于stack exchange




