Python 可以通过多种方式控制打印机进行打印操作,以下是几种常用的方法:
使用 win32print
(Windows 系统)
安装
pip install pywin32
示例代码
import win32print
import win32api
# 获取默认打印机
default_printer = win32print.GetDefaultPrinter()
print(f"默认打印机: {default_printer}")
# 列出所有打印机
printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL)
print("可用打印机:")
for printer in printers:
print(f"- {printer[2]}")
# 打印文本文件
file_to_print = "document.txt"
printer_name = default_printer
# 使用系统命令打印
win32api.ShellExecute(0, "print", file_to_print, f'"{printer_name}"', ".", 0)
使用 cups
(Linux/macOS 系统)
安装
pip install pycups
示例代码
import cups
# 连接CUPS服务器
conn = cups.Connection()
# 列出所有打印机
printers = conn.getPrinters()
print("可用打印机:")
for printer in printers:
print(f"- {printer}")
# 打印文件
printer_name = list(printers.keys())[0] # 使用第一个打印机
file_to_print = "document.pdf"
job_id = conn.printFile(printer_name, file_to_print, "Python Print Job", {})
print(f"打印任务已提交,ID: {job_id}")
使用 reportlab
生成 PDF 并打印
安装
pip install reportlab
示例代码
from reportlab.pdfgen import canvas
import subprocess
# 创建PDF文档
pdf_file = "output.pdf"
c = canvas.Canvas(pdf_file)
c.drawString(100, 750, "Python 打印测试")
c.drawString(100, 730, "这是一份通过Python生成的PDF文档")
c.save()
# 打印PDF (Linux/macOS)
subprocess.run(["lp", pdf_file])
# Windows系统打印
# subprocess.run(["notepad", "/p", pdf_file])
使用 python-escpos
控制热敏打印机
安装
pip install python-escpos
示例代码
from escpos.printer import Usb
# 连接USB打印机 (需替换厂商ID和产品ID)
p = Usb(0x0416, 0x5011)
# 打印内容
p.text("Python ESC/POS 打印测试\n")
p.text("这是一行文本\n")
p.text("----------------\n")
p.barcode("123456789", "EAN13")
p.cut()
# 关闭连接
p.close()
常见问题
1 打印队列管理 (Windows)
import win32print
# 暂停打印机
win32print.SetPrinter(win32print.OpenPrinter(default_printer), 0, None, win32print.PRINTER_CONTROL_PAUSE)
# 恢复打印机
win32print.SetPrinter(win32print.OpenPrinter(default_printer), 0, None, win32print.PRINTER_CONTROL_RESUME)
# 清除打印队列
win32print.SetPrinter(win32print.OpenPrinter(default_printer), 0, None, win32print.PRINTER_CONTROL_PURGE)
2 设置打印份数和双面打印
from win32printing import Printer with Printer(linegap=1) as printer: printer.text("第一页内容") printer.page_break() # 分页 printer.text("第二页内容") # 设置打印份数 printer.job(duplex=True, copies=2) # 双面打印,2份
跨平台打印
import platform
import subprocess
def print_file(filename):
system = platform.system()
if system == "Windows":
# Windows系统
subprocess.run(["notepad", "/p", filename])
elif system == "Linux" or system == "Darwin":
# Linux/macOS系统
subprocess.run(["lp", filename])
else:
raise OSError("不支持的操作系统")
# 使用示例
print_file("document.txt")
总结
-
Windows系统推荐使用
win32print
模块 -
Linux/macOS推荐使用
cups
或直接调用lp
命令 -
热敏/票据打印机使用
python-escpos
-
生成PDF后打印使用
reportlab
+ 系统打印命令 -
跨平台应用需要考虑不同操作系统的兼容性
win32print 模块详解
win32print
是 PyWin32 库的一部分,专门用于 Windows 系统上的打印机控制。它提供了丰富的 API 来管理打印机、打印作业和打印队列。
安装
首先需要安装 PyWin32 库:
pip install pywin32
常用功能
1 获取打印机信息
import win32print
# 获取默认打印机
default_printer = win32print.GetDefaultPrinter()
print(f"默认打印机: {default_printer}")
# 列出所有可用打印机
printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS)
print("可用打印机列表:")
for i, printer in enumerate(printers, 1):
print(f"{i}. {printer[2]}") # printer[2] 是打印机名称
2 打印文本文件
import win32api
file_to_print = "C:\\path\\to\\your\\document.txt"
printer_name = win32print.GetDefaultPrinter()
# 使用 ShellExecute 打印
win32api.ShellExecute(
0, # hwnd
"print", # operation
file_to_print, # file
f'"{printer_name}"', # parameters
".", # directory
0 # show command
)
3 高级打印控制
def print_raw_data(printer_name, data):
"""
直接发送原始数据到打印机
"""
hprinter = win32print.OpenPrinter(printer_name)
try:
hjob = win32print.StartDocPrinter(
hprinter,
1,
("Python RAW Print", None, "RAW")
)
try:
win32print.StartPagePrinter(hprinter)
win32print.WritePrinter(hprinter, data)
win32print.EndPagePrinter(hprinter)
finally:
win32print.EndDocPrinter(hprinter)
finally:
win32print.ClosePrinter(hprinter)
# 示例:打印 ESC/POS 指令
esc_pos_data = b"\x1B\x40" # 初始化打印机
esc_pos_data += b"Hello, Printer!\n"
esc_pos_data += b"\x1B\x69" # 切纸指令
print_raw_data(default_printer, esc_pos_data)
打印作业管理
1 监控打印队列
def monitor_print_queue(printer_name): hprinter = win32print.OpenPrinter(printer_name) try: jobs = win32print.EnumJobs(hprinter, 0, -1, 1) # 获取所有作业 print(f"{printer_name} 上的打印作业:") for job in jobs: print(f"作业ID: {job['JobId']}, 文档: {job['pDocument']}, 状态: {job['Status']}") finally: win32print.ClosePrinter(hprinter) monitor_print_queue(default_printer)
2 控制打印作业
def control_print_job(printer_name, job_id, action):
"""
action:
- "PAUSE": 暂停作业
- "RESUME": 恢复作业
- "DELETE": 删除作业
"""
hprinter = win32print.OpenPrinter(printer_name)
try:
if action == "PAUSE":
win32print.SetJob(hprinter, job_id, 0, None, win32print.JOB_CONTROL_PAUSE)
elif action == "RESUME":
win32print.SetJob(hprinter, job_id, 0, None, win32print.JOB_CONTROL_RESUME)
elif action == "DELETE":
win32print.SetJob(hprinter, job_id, 0, None, win32print.JOB_CONTROL_DELETE)
print(f"作业 {job_id} 已{action}")
finally:
win32print.ClosePrinter(hprinter)
# 示例:暂停第一个打印作业
jobs = win32print.EnumJobs(win32print.OpenPrinter(default_printer), 0, -1, 1)
if jobs:
control_print_job(default_printer, jobs[0]['JobId'], "PAUSE")
打印机设置
1 获取打印机属性
def get_printer_properties(printer_name): hprinter = win32print.OpenPrinter(printer_name) try: properties = win32print.GetPrinter(hprinter, 2) # Level 2 获取详细信息 print("打印机属性:") print(f"状态: {properties['Status']}") print(f"驱动程序: {properties['pDriverName']}") print(f"端口: {properties['pPortName']}") print(f"共享名: {properties['pShareName']}") print(f"位置: {properties['pLocation']}") print(f"默认数据类型: {properties['pDatatype']}") finally: win32print.ClosePrinter(hprinter) get_printer_properties(default_printer)
2 设置打印机属性
def set_printer_defaults(printer_name): hprinter = win32print.OpenPrinter(printer_name) try: # 获取当前设置 defaults = win32print.GetPrinter(hprinter, 2) # 修改设置 defaults["pDatatype"] = "RAW" # 设置默认数据类型为RAW # 应用新设置 win32print.SetPrinter(hprinter, 2, defaults, 0) print("打印机默认设置已更新") finally: win32print.ClosePrinter(hprinter)
常见问题
1 错误处理
import win32con try: hprinter = win32print.OpenPrinter("不存在的打印机") except win32print.error as e: if e.winerror == win32con.ERROR_INVALID_PRINTER_NAME: print("错误: 打印机名称无效") else: print(f"打印机错误: {e.strerror}")
2 打印到文件
def print_to_file(printer_name, output_file):
hprinter = win32print.OpenPrinter(printer_name)
try:
# 设置打印到文件
attributes = win32print.GetPrinter(hprinter, 2)
attributes["pPortName"] = output_file
win32print.SetPrinter(hprinter, 2, attributes, 0)
# 执行打印
hjob = win32print.StartDocPrinter(hprinter, 1, ("Print to File", None, "RAW"))
win32print.StartPagePrinter(hprinter)
win32print.WritePrinter(hprinter, b"Test content printed to file")
win32print.EndPagePrinter(hprinter)
win32print.EndDocPrinter(hprinter)
print(f"内容已打印到文件: {output_file}")
finally:
# 恢复原始端口设置
attributes["pPortName"] = "FILE:"
win32print.SetPrinter(hprinter, 2, attributes, 0)
win32print.ClosePrinter(hprinter)
print_to_file(default_printer, "C:\\output.prn")
高级应用:自定义打印对话框
import win32ui
import win32con
from pywin.mfc import dialog
class PrintDialog(dialog.PrintDialog):
def __init__(self):
dialog.PrintDialog.__init__(self, win32ui.CreatePrinterDC())
def DoModal(self):
self.pd.Flags |= win32con.PD_RETURNDC | win32con.PD_ALLPAGES | win32con.PD_NOSELECTION
return dialog.PrintDialog.DoModal(self)
# 使用打印对话框
dlg = PrintDialog()
if dlg.DoModal() == win32con.IDOK:
dc = dlg.GetPrinterDC()
# 使用dc进行打印操作...
dc.StartDoc("Python Print Job")
dc.StartPage()
dc.TextOut(100, 100, "使用打印对话框打印的文本")
dc.EndPage()
dc.EndDoc()
总结
win32print 模块提供了 Windows 平台上完整的打印机控制功能,包括:
-
打印机枚举和选择
-
打印作业管理
-
打印机属性配置
-
原始数据打印
-
打印队列监控
对于需要精细控制打印过程的 Windows 应用程序开发,win32print 是最佳选择。对于跨平台需求,可以考虑结合其他方法或使用专门的打印服务库。