Python编程: 打印机打印

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")

总结

  1. Windows系统推荐使用 win32print 模块

  2. Linux/macOS推荐使用 cups 或直接调用 lp 命令

  3. 热敏/票据打印机使用 python-escpos

  4. 生成PDF后打印使用 reportlab + 系统打印命令

  5. 跨平台应用需要考虑不同操作系统的兼容性

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 是最佳选择。对于跨平台需求,可以考虑结合其他方法或使用专门的打印服务库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值