Windows系统下用Python实时获取打印机详细状态的技术咨询
Windows下Python实时获取打印机详细状态解决方案
问题描述
在Windows系统中需通过Python实时获取打印机的详细状态(如机门打开、卡纸、缺墨粉等)并展示,但现有代码存在两个核心问题:
- 仅支持单次状态查询,无法实现实时监控
- 仅能获取暂停、空闲、离线等基础状态,无法捕获机门打开、缺墨粉等详细异常状态
原问题代码
def GetPrinterStatus(self, printerName): pythoncom.CoInitialize() status = "" try: wmi = win32com.client.Dispatch("WbemScripting.SWbemLocator") service = wmi.ConnectServer(".", "root\\cimv2") printers = service.ExecQuery(f"SELECT * FROM Win32_Printer WHERE Name = '{printerName}'") for printer in printers: if printer.PrinterState == 0 or printer.PrinterState == 0: status = status + "IDLE" elif printer.PrinterState == 1 or printer.PrinterState == 1: status = status + "PAUSED" elif printer.PrinterState == 2 or printer.PrinterState == 2: status = status + "Printer Error" elif printer.PrinterState == 4 or printer.PrinterState == 4: status = status + "Pending Deletion" elif printer.PrinterState == 8 or printer.PrinterState == 8: status = status + "Paper Jam" elif printer.PrinterState == 16 or printer.PrinterState == 10: status = status + "Paper Out" elif printer.PrinterState == 32 or printer.PrinterState == 20: status = status + "Manual Feed" elif printer.PrinterState == 64 or printer.PrinterState == 40: status = status + "Page Problem" elif printer.PrinterState == 128 or printer.PrinterState == 80: status = status + "OFFLINE" elif printer.PrinterState == 256 or printer.PrinterState == 100: status = status + "I/O Active" elif printer.PrinterState == 512 or printer.PrinterState == 200: status = status + "BUSY" elif printer.PrinterState == 1024 or printer.PrinterState == 400: status = status + "PRINTING" elif printer.PrinterState == 2048 or printer.PrinterState == 800: status = status + "Output Bin Full" elif printer.PrinterState == 4096 or printer.PrinterState == 1000: status = status + "Not Available" elif printer.PrinterState == 8192 or printer.PrinterState == 2000: status = status + "WAITING" elif printer.PrinterState == 16384 or printer.PrinterState == 4000: status = status + "PROCESSING" elif printer.PrinterState == 32768 or printer.PrinterState == 8000: status = status + "Initializing" elif printer.PrinterState == 65536 or printer.PrinterState == 10000: status = status + "Warming Up" elif printer.PrinterState == 131072 or printer.PrinterState == 20000: status = status + "Toner Low" elif printer.PrinterState == 262144 or printer.PrinterState == 40000: status = status + "No Toner" elif printer.PrinterState == 524288 or printer.PrinterState == 80000: status = status + "Page Punt" elif printer.PrinterState == 1048576 or printer.PrinterState == 100000: status = status + "User Intervention" elif printer.PrinterState == 2097152 or printer.PrinterState == 200000: status = status + "Out of Memory" elif printer.PrinterState == 4194304 or printer.PrinterState == 400000: status = status + "Printer Door Open" elif printer.PrinterState == 8388608 or printer.PrinterState == 800000: status = status + "Unknown Server" elif printer.PrinterState == 6777216 or printer.PrinterState == 1000000: status = status + "Power Save" finally: pythoncom.CoUninitialize() return status
核心问题分析
- 状态判断逻辑错误:
PrinterState是位掩码类型,多个状态可同时存在(如卡纸+机门打开),原代码用==判断单一值,无法识别复合状态,也会遗漏大部分详细异常。 - 未利用扩展状态属性:Win32_Printer提供的
ExtendedDetectedErrorState属性包含更精准的错误状态,原代码未使用该属性,导致无法获取缺墨、机门打开等信息。 - 无实时机制:原代码仅执行单次查询,未实现定时重复查询或事件监听,无法做到实时状态更新。
解决方案
1. 修正状态获取逻辑
通过位运算解析PrinterState和ExtendedDetectedErrorState的位掩码,获取完整的打印机状态:
import pythoncom import win32com.client # 定义PrinterState对应的状态映射(位掩码) PRINTER_STATES = { 0x00000001: "已暂停", 0x00000002: "打印机错误", 0x00000004: "待删除", 0x00000008: "卡纸", 0x00000010: "缺纸", 0x00000020: "手动进纸", 0x00000040: "页面问题", 0x00000080: "离线", 0x00000100: "I/O活动中", 0x00000200: "忙碌", 0x00000400: "正在打印", 0x00000800: "出纸槽已满", 0x00001000: "不可用", 0x00002000: "等待中", 0x00004000: "处理中", 0x00008000: "初始化中", 0x00010000: "预热中", 0x00020000: "墨粉不足", 0x00040000: "无墨粉", 0x00080000: "页面放弃", 0x00100000: "需要用户干预", 0x00200000: "内存不足", 0x00400000: "打印机机门打开", 0x00800000: "未知服务器", 0x04000000: "省电模式" } # 定义ExtendedDetectedErrorState对应的扩展状态映射 EXTENDED_STATES = { 1: "无错误", 2: "缺纸", 4: "卡纸", 8: "墨粉不足", 16: "无墨粉", 32: "机门打开", 64: "需要用户干预", 128: "输出槽满", 256: "内存不足", 512: "正在打印", 1024: "正在处理", 2048: "预热中", 4096: "离线", 8192: "暂停", 16384: "初始化中", 32768: "省电模式" } def get_printer_status(printer_name): pythoncom.CoInitialize() status_list = [] try: wmi = win32com.client.Dispatch("WbemScripting.SWbemLocator") service = wmi.ConnectServer(".", "root\\cimv2") # 查询指定打印机 printers = service.ExecQuery(f"SELECT * FROM Win32_Printer WHERE Name = '{printer_name}'") for printer in printers: # 解析PrinterState位掩码 state = printer.PrinterState for mask, desc in PRINTER_STATES.items(): if state & mask: status_list.append(desc) # 解析ExtendedDetectedErrorState位掩码,补充更详细状态 extended_state = printer.ExtendedDetectedErrorState if extended_state: for mask, desc in EXTENDED_STATES.items(): if extended_state & mask and desc not in status_list: status_list.append(desc) # 无任何状态时默认显示空闲 if not status_list: status_list.append("空闲") finally: pythoncom.CoUninitialize() return " | ".join(status_list)
2. 实现实时监控
提供两种实时监控方式,按需选择:
方式一:定时轮询(简单易实现)
通过定时重复查询打印机状态,实现实时展示:
import time def realtime_monitor(printer_name, interval=2): """ 实时监控打印机状态 :param printer_name: 打印机名称 :param interval: 查询间隔(秒),默认2秒 """ print(f"开始实时监控打印机: {printer_name}") print("------------------------------") try: while True: current_status = get_printer_status(printer_name) # 覆盖当前行输出,避免刷屏 print(f"\r当前状态: {current_status}", end="") time.sleep(interval) except KeyboardInterrupt: print("\n监控已停止") # 调用示例(替换为你的打印机名称) if __name__ == "__main__": TARGET_PRINTER = "你的打印机名称" realtime_monitor(TARGET_PRINTER)
方式二:WMI事件监听(高效,状态变更时触发)
监听WMI的打印机属性变更事件,仅在状态变化时更新,减少资源消耗:
def monitor_printer_events(printer_name): """ 通过WMI事件监听打印机状态变更 """ pythoncom.CoInitialize() try: wmi = win32com.client.Dispatch("WbemScripting.SWbemLocator") service = wmi.ConnectServer(".", "root\\cimv2") # 创建事件查询,每2秒检查一次状态变更 query = f"SELECT * FROM __InstanceModificationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Printer' AND TargetInstance.Name = '{printer_name}'" watcher = service.ExecNotificationQuery(query) print(f"开始监听打印机 {printer_name} 的状态变更...") while True: # 等待事件触发 event = watcher.NextEvent() # 获取最新状态并打印 current_status = get_printer_status(printer_name) print(f"\n状态变更: {current_status}") except KeyboardInterrupt: print("\n监听已停止") finally: pythoncom.CoUninitialize() # 调用示例 if __name__ == "__main__": TARGET_PRINTER = "你的打印机名称" monitor_printer_events(TARGET_PRINTER)
使用说明
- 确保已安装依赖库:
pip install pywin32 - 替换代码中的
TARGET_PRINTER为你的实际打印机名称(可在Windows打印机设置中查看) - 运行代码后,即可实时获取并展示打印机的详细状态
内容的提问来源于stack exchange,提问作者John0211
相关产品推荐
相关产品推荐

