告别Word和PDF!用Python的win32ui库直接驱动打印机,搞定标签打印(附完整代码)

Python驱动打印机实战:高效标签打印解决方案

每次打开Word调整格式、导出PDF再打印的繁琐流程,是否已经让你对批量标签打印任务感到厌倦?在物流仓储、零售库存、医疗标本等需要高频打印标签的场景中,传统打印方式的效率瓶颈尤为明显。本文将介绍如何利用Python的win32ui库直接与打印机硬件对话,实现无需中间文件的精准打印控制。

1. 环境准备与基础配置

1.1 安装必要依赖

开始前需要确保系统满足以下条件:

  • Windows操作系统(win32ui库仅支持Windows)
  • Python 3.6及以上版本
  • 目标打印机已正确安装驱动

通过pip安装所需库:

pip install pywin32 pillow

1.2 打印机连接检测

使用以下代码检测可用打印机列表:

import win32print def list_printers(): printers = win32print.EnumPrinters(2) # 参数2表示枚举本地安装的打印机 return [printer[2] for printer in printers] if __name__ == '__main__': print("可用打印机:", list_printers())

注意:如果使用网络打印机,请确保打印机共享设置正确且网络连通

2. 核心打印控制技术

2.1 设备上下文与打印会话

win32ui库通过设备上下文(DC)与打印机交互。典型打印流程包括:

  1. 创建设备上下文对象
  2. 关联特定打印机
  3. 开始打印任务
  4. 绘制页面内容
  5. 结束页面和任务

基础打印框架代码:

import win32ui import win32con def basic_print(printer_name="默认打印机"): hDC = win32ui.CreateDC() hDC.CreatePrinterDC(printer_name) try: hDC.StartDoc("Python打印任务") hDC.StartPage() # 在这里添加绘制内容 hDC.EndPage() hDC.EndDoc() except Exception as e: hDC.AbortDoc() raise e

2.2 字体控制与文本定位

精确控制文本样式是标签打印的关键。win32ui.CreateFont支持的主要参数:

参数类型说明常用值
heightint字体高度(像素)20-200
widthint字体宽度(像素)0(自动)
escapementint文本行倾斜(0.1度)0-3600
weightint字体粗细400(常规),700(粗体)
italicbool斜体True/False
underlinebool下划线True/False
namestr字体名称"宋体","Arial"

文本定位示例:

font_spec = { 'name': '黑体', 'height': 80, 'weight': 700, 'italic': False } font = win32ui.CreateFont(font_spec) hDC.SelectObject(font) hDC.TextOut(100, 200, "重要标签") # (x, y, text)

3. 高级标签打印实现

3.1 动态标签模板设计

针对常见的标签打印需求,我们可以设计可配置的模板系统:

class LabelTemplate: def __init__(self, printer_name, paper_size=(800, 600)): self.printer_name = printer_name self.width, self.height = paper_size self.elements = [] def add_text(self, x, y, content, font_config): self.elements.append(('text', x, y, content, font_config)) def print_label(self): hDC = win32ui.CreateDC() hDC.CreatePrinterDC(self.printer_name) hDC.StartDoc("标签打印") hDC.StartPage() for element in self.elements: if element[0] == 'text': _, x, y, content, font_config = element font = win32ui.CreateFont(font_config) hDC.SelectObject(font) hDC.TextOut(x, y, content) hDC.EndPage() hDC.EndDoc()

3.2 条码与二维码集成

结合Pillow库生成条码图像并打印:

from PIL import Image, ImageDraw import barcode from io import BytesIO def generate_barcode(code, barcode_type='code128'): """生成条码图像""" writer = barcode.get_barcode_class(barcode_type) img = writer(code).render() return img def print_barcode(hDC, img, position, size): """打印条码图像""" img = img.resize(size) dib = ImageWin.Dib(img) dib.draw(hDC.GetHandleOutput(), position)

4. 实战:医疗标本标签系统

4.1 完整案例实现

以下是一个医疗标本标签打印的完整示例:

import win32ui import time from datetime import datetime class MedicalLabelPrinter: def __init__(self, printer_name): self.printer_name = printer_name self.label_width = 800 self.label_height = 500 def print_specimen_label(self, patient_info, test_items): hDC = win32ui.CreateDC() hDC.CreatePrinterDC(self.printer_name) try: hDC.StartDoc("医疗标本标签") hDC.StartPage() # 打印医院LOGO区域 self._print_header(hDC) # 打印患者信息 self._print_patient_info(hDC, patient_info) # 打印检验项目 self._print_test_items(hDC, test_items) # 打印时间条码 self._print_time_barcode(hDC) hDC.EndPage() hDC.EndDoc() except Exception as e: hDC.AbortDoc() raise e def _print_header(self, hDC): font = win32ui.CreateFont({ 'name': '黑体', 'height': 60, 'weight': 700 }) hDC.SelectObject(font) hDC.TextOut(50, 30, "XX医院检验科") hDC.MoveTo(40, 100) hDC.LineTo(self.label_width - 40, 100) def _print_patient_info(self, hDC, info): font_normal = win32ui.CreateFont({'name': '宋体', 'height': 35}) font_emph = win32ui.CreateFont({ 'name': '宋体', 'height': 40, 'weight': 700 }) hDC.SelectObject(font_normal) hDC.TextOut(50, 120, "姓名:") hDC.SelectObject(font_emph) hDC.TextOut(150, 120, info['name']) hDC.SelectObject(font_normal) hDC.TextOut(50, 170, "病历号:") hDC.SelectObject(font_emph) hDC.TextOut(150, 170, info['medical_id']) def _print_test_items(self, hDC, items): font = win32ui.CreateFont({'name': '宋体', 'height': 30}) hDC.SelectObject(font) y_pos = 230 hDC.TextOut(50, y_pos, "检验项目:") y_pos += 40 for i, item in enumerate(items): if i > 0: hDC.TextOut(150, y_pos, "、") y_pos += 40 hDC.TextOut(150, y_pos, item) def _print_time_barcode(self, hDC): now = datetime.now().strftime("%Y%m%d%H%M") barcode_img = generate_barcode(now) print_barcode(hDC, barcode_img, (50, 350), (700, 100)) font = win32ui.CreateFont({'name': 'Arial', 'height': 25}) hDC.SelectObject(font) hDC.TextOut(300, 460, now)

4.2 性能优化技巧

  1. 批量打印优化

    def batch_print_labels(printer_name, label_data_list): hDC = win32ui.CreateDC() hDC.CreatePrinterDC(printer_name) hDC.StartDoc("批量标签打印") for data in label_data_list: hDC.StartPage() # 绘制标签内容 draw_label_content(hDC, data) hDC.EndPage() hDC.EndDoc()
  2. 打印机缓存利用

    • 复用设备上下文对象
    • 预加载常用字体
    • 使用打印机原生指令模式(需查阅特定打印机手册)
  3. 错误处理与重试机制

    def safe_print(print_func, max_retries=3): for attempt in range(max_retries): try: return print_func() except win32ui.error as e: if attempt == max_retries - 1: raise time.sleep(1)

5. 常见问题排查

5.1 打印内容偏移调整

当打印内容出现位置偏差时,可通过以下步骤校准:

  1. 打印测试页记录偏移量
  2. 调整代码中的坐标参数
  3. 考虑打印机自身的页边距设置

校准代码示例:

def calibrate_position(printer_name): hDC = win32ui.CreateDC() hDC.CreatePrinterDC(printer_name) hDC.StartDoc("校准测试页") hDC.StartPage() # 打印参考网格 for x in range(0, 1000, 50): hDC.MoveTo(x, 0) hDC.LineTo(x, 1000) hDC.TextOut(x, 10, str(x)) for y in range(0, 1000, 50): hDC.MoveTo(0, y) hDC.LineTo(1000, y) hDC.TextOut(10, y, str(y)) hDC.EndPage() hDC.EndDoc()

5.2 特殊打印机适配

不同品牌打印机可能需要特殊处理:

打印机类型注意事项解决方案
热敏标签机纸张尺寸固定精确设置页面尺寸
票据打印机自动切纸功能发送切纸指令
工业打印机高速模式优化绘图指令

针对斑马打印机的指令示例:

def send_zpl_command(printer_name, zpl_command): hPrinter = win32print.OpenPrinter(printer_name) try: hJob = win32print.StartDocPrinter(hPrinter, 1, ("ZPL指令", None, "RAW")) win32print.StartPagePrinter(hPrinter) win32print.WritePrinter(hPrinter, zpl_command.encode('utf-8')) win32print.EndPagePrinter(hPrinter) win32print.EndDocPrinter(hPrinter) finally: win32print.ClosePrinter(hPrinter)