本篇目录
之前写了一篇“<a href="https://ranjuan.cn/win-python-usb-com/">windows下python实现usb收发通信</a>”的文章,是使用底层库来实现python与usb的收发通信;如果你的热敏打印机支持标准的ESC/POS指令的话是可以使用python-escpos这个库(号称python下的打印机神器)进行打印机操作,这个库虽然连接、控制、打印都相对比较简单,但是如果相同型号的打印机连接到同一个电脑设备上,那么它可能只会随机地选择其中一台打印机打印,无法指定打印机!这也是为什么有了之前那边使用python直接与usb进行通信的文章。后来又研究了下escpos这个库的源码,发现其实可以对usb的open方法进行改造就可以实现通过usb设备序列号来区分相同型号的打印机了(有些打印机厂家可能usb序列号没有或者都一样,那么最好建议问厂家能不能给个改写序列号的软件/固件,或者是提供一个版本号查询方法通过版本号来区分打印机设备)<br>
一、准备工作
1、我这里是python3.12(正常python3.x应该都行)
2、安装python-escpos,如果运行时提示缺少包那么就把缺失的安装一遍
pip install python-escpos3、找到打印机的厂商ID和产品ID的设备(在设备管理器里面可以看到,我上面提到的文章里也有介绍,不会的百度)
4、找到你打印机的设备序列号,可以网上找下怎么查询usb序列号,也可以使用我下面提供的源码来进行查询
二、改造后的源码
注意设备厂商ID和产品ID要选对,否则匹配不上,另外设备序列号如果不知道怎么获取可以随便填写赋值serial_number,程序运行的时候会打印已知的序列号,打印出来后复制并替换serial_number值,然后重新再运行一遍程序即可。
import loggingfrom typing import Optional, Typefrom escpos.printer.usb import dependency_usbfrom escpos.printer import Usbimport usb.coreimport usb.utilfrom escpos.exceptions import DeviceNotFoundError, USBNotFoundError# 重写usb连接方式调用class CustomUSBPrinter(Usb):def __init__(self, vendor_id, product_id, serial_number=None, *args, **kwargs):self.serial_number = serial_numberself.idVendor= vendor_idself.idProduct = product_idtry:super().__init__(idVendor=vendor_id, idProduct=product_id, *args, **kwargs)except (USBNotFoundError, usb.core.USBError):# 静默捕获异常,不退出程序print("USB device not found or error")pass@dependency_usbdef open(self, raise_not_found: bool = True) -> None:"""重写 open 方法,支持根据序列号筛选设备"""# 查找所有匹配厂商ID和产品ID的设备#print('重写的方法usb')if self._device:self.close()# Open devicetry:if self.serial_number: #需要按序列号来查找设备devs = usb.core.find(find_all=True, idVendor=self.idVendor, idProduct=self.idProduct)for dev in devs:try:current_serial = usb.util.get_string(dev, dev.iSerialNumber)print(f'已发现usb设备序列号:{current_serial}') # 如果列出发现的设备对应的序列号,可以复制后续使用if current_serial == self.serial_number:self.device = devbreak # 找第一个匹配的except (usb.USBError, UnicodeDecodeError):print('发生了某些usb设备错误')continueelse: # 原逻辑self.device: Optional[Type[usb.core.Device]] = usb.core.find(**self.usb_args)assert self.device, USBNotFoundError(f"Device {tuple(self.usb_args.values())} not found"+ " or cable not plugged in.")# 配置USB连接self._check_driver()self._configure_usb()except (AssertionError, usb.core.USBError) as e:# Raise exception or log error and cancelself.device = Noneif raise_not_found:raise DeviceNotFoundError(f"Unable to open USB printer on {tuple(self.usb_args.values())}:"+ f"n{e}")else:logging.error("USB device %s not found", tuple(self.usb_args.values()))returnlogging.info("USB printer enabled")# 下面是正式使用…………# 示例:连接指定厂商ID、产品ID和序列号的设备idVendor = 0x5a5aidProduct = 0x8009serial_number= '206035763031' # 序列号,如果已知idVendor、idProduct 序列号可以随便填,程序会打印出来,然后复制过来替换本序列号in_ep= 0x81 # python库默认的是0x82 根据实际的来out_ep= 0x01 # 有的是0x02try:# 尝试连接打印机printer = CustomUSBPrinter(vendor_id=idVendor,product_id=idProduct,serial_number=serial_number,in_ep=in_ep,out_ep=out_ep)#printer = CustomUSBPrinter(vendor_id=idVendor, product_id=idProduct, in_ep=in_ep, out_ep=out_ep)connected = printer.device is not None # 确认设备存在except (DeviceNotFoundError, usb.core.USBError):printer = Noneconnected = False# 检查连接状态if connected:# 正常连接成功,还应该检测打印机状态; 部分打印机状态异常时也能接收到并缓存打印指令,打印机不断电情况下修复错误后会打印缓存中的指令!print("USB 打印机已连接")printer.text("--测试打印n")printer.qr(content='https://www.baidu.com',size=6) # 二维码printer.barcode('6935103100088', 'EAN13', 64, 2, '', '') # 条码img_src = "ticket_at.png"printer.image(img_src, impl="bitImageRaster")printer.close()else:print("USB 打印机未连接")
三、提示
充分利用好AI,问问文心一言、DeepSeek,他们也能解决很多代码片段问题!
发表评论