从零到实战:用Python脚本精确控制打印机的完整指南
目录导读
- 为什么需要脚本控制打印机? —— 效率与自动化的核心价值
- 控制打印机前的准备工作 —— 硬件、驱动与Python环境搭建
- 核心操控技术 —— win32print库深度解析(含代码示例)
- 进阶实战:批量打印PDF/Word文档的自动化脚本
- 常见报错与解决方案 —— 排除“卡纸”“脱机”等玄学问题
- 高频问答(Q&A) —— 解决你最后的疑虑
为什么需要脚本控制打印机?
在日常办公或开发中,手动点击“打印”按钮重复操作不仅耗时,且容易出错,批量打印100张带不同编号的标签、定时自动打印报表、根据数据库内容动态生成单据,通过脚本,我们可以实现无人值守打印、静默打印(不弹出对话框)、以及精确控制打印份数、纸张方向、双面模式等,其本质是调用操作系统底层的打印机API,绕过GUI交互,直接向打印机发送指令。

准备工作:环境与依赖
在开始写代码之前,请确保:
- 硬件:打印机已正确连接电脑并安装官方驱动,且在“控制面板 > 设备和打印机”中设为默认打印机(或记住其名称)。
- Python环境:建议使用Python 3.8+,并安装核心库
pywin32(或仅安装win32print,它是前者的子模块)。pip install pywin32
- 系统限制:此方案主要针对Windows系统(因使用Win32 API),对于Linux/macOS,可改用
cups或lp命令,但本文聚焦Windows。
核心操控技术:win32print深度解析
win32print 是连接Python与Windows打印系统的桥梁,其底层封装了GDI(图形设备接口)和打印机驱动API,以下是最常用的三个函数:
-
win32print.EnumPrinters()—— 获取打印机列表import win32print printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS) for p in printers: print(p[2]) # 打印打印机名称 -
win32print.OpenPrinter()与win32print.StartDocPrinter()—— 开启打印任务 这是最底层的“原始数据”发送方式,通常用于直接发送文本或PCL/PostScript指令,但如果你要打印PDF或图片,更推荐使用上层的win32api.ShellExecute或os.startfile(),因为它们会自动调用关联程序(如Adobe Reader)并触发打印。 -
win32print.SetJob()—— 控制任务状态(暂停/恢复/取消)# 获取当前打印队列中的任务 handle = win32print.OpenPrinter(printer_name) jobs = win32print.EnumJobs(handle, 0, -1, win32print.JOB_STATUS_ALL) for job in jobs: job_id = job['JobId'] # 取消任务 win32print.SetJob(handle, job_id, 0, None, win32print.JOB_CONTROL_DELETE) win32print.ClosePrinter(handle)
进阶实战:批量打印PDF/Word文档的自动化脚本
要想实现“一键打印整个文件夹中的PDF”,最稳定的是调用系统默认程序,然后通过模拟快捷键Ctrl+P来触发打印,但这种方式不够“静默”,更好的方案是通过COM接口操作Office或使用专库pdf2print,下面是一段更实用、无弹窗的打印图片和文本文件的例子:
import os
import win32print
import win32ui
from PIL import Image
def print_image(img_path, printer_name=None, copies=1):
if not printer_name:
printer_name = win32print.GetDefaultPrinter()
# 创建DC(设备上下文)
hprinter = win32print.OpenPrinter(printer_name)
try:
# 获取打印机DC句柄
devmode = win32print.GetPrinter(hprinter, 2)["pDevMode"]
# 加载图片并调整尺寸
image = Image.open(img_path)
width, height = image.size
# 创建打印DC
pr_dc = win32ui.CreateDC()
pr_dc.CreatePrinterDC(printer_name)
pr_dc.StartDoc(img_path)
pr_dc.StartPage()
# 缩放图片以适配纸张(这里简化处理)
# 实际需计算比例并调用StretchBlt
pr_dc.EndPage()
pr_dc.EndDoc()
finally:
win32print.ClosePrinter(hprinter)
# 批量打印当前目录所有图片
for f in os.listdir('.'):
if f.lower().endswith(('.png', '.jpg', '.jpeg')):
print(f"正在打印:{f}")
print_image(f)
注意:上述代码涉及图像缩放与DPI计算,真正的生产级脚本应使用
win32ui的BitBlt来做无损输出,如果只是想快速实现,推荐安装pandas+pathlib+win32api,利用shellapi.ShellExecuteW的printto命令。
常见报错与解决方案
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
| “PrintNotFound”错误 | 打印机名称错误或驱动未安装 | 使用win32print.EnumPrinters()打印所有名称,复制确切字符串。 |
| 脚本运行无反应 | 打印页面被隐藏或队列阻塞 | 检查打印机状态,先手动打印测试页排除硬件故障。 |
| PDF打印失败 | 关联程序未启动或受保护 | 改用Acrobat的COM接口,或转换PDF为图片后打印。 |
| 权限不足 | 服务账户无访问驱动权限 | 以管理员身份运行Python或Windows服务。 |
高频问答(Q&A)
Q1:脚本能控制打印机的双面打印吗?
A:可以,你需要修改devmode中的dmDuplex字段(1=单面,2=双面长边,3=双面短边),但这要求驱动支持,建议在打印机属性中预先设置默认双面,然后脚本中不修改该字段。
Q2:如何在Linux上实现类似功能?
A:使用cups打印系统,调用subprocess.run(['lp', '-d', 'printer_name', '-n', '2', 'file.pdf']),Python库如pycups也提供封装。
Q3:脚本如何实现“静默打印”而不弹出保存PDF对话框?
A:关键在于不要使用os.startfile(),它会调用Adobe Reader并弹出窗口,请使用win32print直接发送原始数据,或者使用libreoffice的headless模式转换并打印。
Q4:监控打印任务完成状态?
A:可以使用win32print.EnumJobs轮询队列,当任务列表为空时即为打印完成,更高级的是注册系统打印事件,但需要写C++扩展或使用win32event。
结束语:掌握脚本控制打印机,本质是拥抱自动化思维,从简单的文本打印到复杂的混合文档批处理,Python的win32print为你提供了强大的底层接口,本文给出的示例代码(请自行补齐具体细节)已能覆盖80%的日常需求,如果你的场景涉及网络打印机或云打印,只需调整连接字符串即可,希望这篇指南能帮你从“手动点打印”升级为“一键全自动”。