Python调用win32print使用Microsoft Print to PDF报错如何解决
需求背景
需要实现批量PDF转写功能:将现有PDF输出为新的无加密PDF文件。由于部分待处理PDF使用PyPDF2无法解密的code 4加密方案,原计划通过Microsoft Print to PDF虚拟打印生成可正常读取的新文件,后续再通过PyPDF2的PdfFileReader加载生成文件,裁剪去除冗余页面。
问题复现
初始实现代码
import win32print as wp printer = wp.OpenPrinter('Microsoft Print to PDF') print_job = wp.StartDocPrinter(printer, 1, (".\in.pdf", ".\out.pdf", "RAW")) wp.StartPagePrinter(printer)
运行报错信息
----> 2 print_job = wp.StartDocPrinter(printer, 1, (".\in.pdf", ".\out.pdf", "RAW")) 3 wp.StartPagePrinter(printer) error: (5, 'StartDocPrinter', 'Access is denied.')
报错原因与修复方案
核心报错原因
- 权限不足:直接调用
OpenPrinter打开打印机时默认使用最低权限,没有提交打印任务的操作权限,会触发拒绝访问报错。 - 逻辑错误:Microsoft Print to PDF虚拟打印机不支持直接接收
RAW类型的PDF原始数据,跳过渲染步骤直接往打印端口写文件的逻辑本身无法生成正确的PDF,即使解决权限问题也无法得到预期输出。 - 路径不规范:代码中使用
.\in.pdf这类相对路径,打印进程的工作目录和脚本运行目录不一致时会找不到目标文件,也会触发类权限报错。
可行实现方案
方案1:修正虚拟打印逻辑
不要直接操作底层打印端口,通过系统标准打印调用触发虚拟打印,避免权限问题:
注意:使用该方案前需要先修改对应注册表项,关闭Microsoft Print to PDF的「保存文件时询问」弹窗,否则批量处理时会弹出交互窗口卡住流程。
- 提前配置虚拟打印机默认输出路径
- 临时将系统默认打印机切换为Microsoft Print to PDF,调用系统打印接口处理文件,任务完成后切回原默认打印机
参考实现片段:
import os import win32print import time # 保存原有默认打印机配置 origin_printer = win32print.GetDefaultPrinter() # 临时切换默认打印机为虚拟PDF打印机 win32print.SetDefaultPrinter("Microsoft Print to PDF") # 待处理文件必须使用绝对路径 input_pdf = r"C:\workspace\in.pdf" # 触发系统打印动作 os.startfile(input_pdf, "print") # 等待打印队列任务完成,可根据文件大小调整等待时长 time.sleep(5) # 恢复原有默认打印机 win32print.SetDefaultPrinter(origin_printer)
方案2:更高效的替代方案(推荐)
不需要走虚拟打印流程,直接替换PDF处理库即可解决大部分加密PDF读取问题:
- 使用
pymupdf(fitz)库替代PyPDF2,绝大多数PyPDF2无法解密的code 4加密PDF,pymupdf都可以直接加载读取,直接完成页面裁剪、另存操作,处理速度比虚拟打印快10倍以上,没有系统打印配置的兼容问题。 - 如果遇到pymupdf也无法加载的加密文件,可以调用SumatraPDF的静默打印能力,通过命令行参数直接指定输入文件、目标打印机、输出路径,不需要操作win32print底层接口,不会触发权限报错,参考命令:
SumatraPDF.exe -print-to "Microsoft Print to PDF" -output "C:\workspace\out.pdf" "C:\workspace\in.pdf" -silent
内容的提问来源于stack exchange,提问作者Nikolas
相关产品推荐
相关产品推荐

