You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ReportLab在Python中打印PDF时偶发打印错误求助

偶发性打印机错误排查求助

使用ReportLab生成PDF并通过Python脚本打印时,出现无规律的偶发性错误:有时连续成功打印10次后触发,有时每隔一次就报错。出错时PDF会卡在打印队列中,只能通过插拔打印机暂时恢复,目前无法获取完整错误详情,希望排查代码或脚本层面的问题。

import os
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import win32print
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import landscape, portrait
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# Set up Google Sheets API credentials
scope = ['https://spreadsheets.google.com/feeds',
         'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('creds.json', scope)
client = gspread.authorize(creds)

# Set up printer name and font
printer_name = "Rollo Printer"
font_path = "arial.ttf"

# Register Arial font
pdfmetrics.registerFont(TTFont('Arial', font_path))

# Open the Google Sheet and select Label and Claims worksheets
sheet_url = "https://docs.google.com/spreadsheets/d/1eRO-30eIZamB5sjBp-Mz2QMKCfGxV037MQO8nS7G7AI/edit#gid=1988901382"
label_sheet = client.open_by_url(sheet_url).worksheet("Label")
claims_sheet = client.open_by_url(sheet_url).worksheet("Claims")

# Get the number of label copies to print
num_copies = int(label_sheet.acell("F2").value)

# Set up label filename and PDF canvas
label_file = "label.pdf"
label_canvas = canvas.Canvas(label_file, pagesize=landscape((400, 250)),bottomup=432)

# Write label text to PDF canvas
label_text = label_sheet.get_all_values()
x_pos = 10  # set initial x position
y_pos = 260  # set initial y position
line_height = 20  # set line height for text
label_canvas.setFont('Arial', 20)
for row in label_text:
    for col in row:
        textobject = label_canvas.beginText()
        textobject.setFont('Arial', 20)
        textobject.setTextOrigin(x_pos, y_pos)
        lines = col.split("\n")
        for line in lines:
            textobject.textLine(line)
            y_pos -= line_height
        label_canvas.drawText(textobject)
        x_pos += 145
        y_pos = 260
    x_pos = 10

# Save the label PDF and print to the printer
label_canvas.save()
for i in range(num_copies):
    os.startfile(label_file, 'printto', printer_name, "", 1)

# Set up claims filename and PDF canvas
claims_file = "claims.pdf"
claims_canvas = canvas.Canvas(claims_file, pagesize=landscape((400, 250)),bottomup=432)

# Write claims text to PDF canvas
claims_text = claims_sheet.get_all_values()
x_pos = 10
y_pos = 260  # set initial y position
line_height = 20
claims_canvas.setFont('Arial', 20)
for row in claims_text:
    for col in row:
        textobject = claims_canvas.beginText()
        textobject.setFont('Arial', 20)
        textobject.setTextOrigin(x_pos, y_pos)
        lines = col.split("\n")
        for line in lines:
            textobject.textLine(line)
            y_pos -= line_height
        claims_canvas.drawText(textobject)
        x_pos += 145
        y_pos = 260
    x_pos = 10

# Save the claims PDF and print to the printer
claims_canvas.save()
os.startfile(claims_file, 'printto', printer_name, "", 1)

排查建议

  • 优化批量打印逻辑:当前循环调用os.startfile提交多份打印任务,易引发打印机队列拥堵或资源竞争。建议将多份标签合并为一个多页PDF后一次性打印,或在每次打印调用后添加2-3秒延迟,确保前一个任务处理完成。
  • 确保PDF文件资源释放:canvas.save()后文件可能仍处于占用状态,直接打印易引发读取异常。可添加短暂延迟,或在打印完成后删除临时PDF文件(无需保留时),示例:
    import time
    label_canvas.save()
    time.sleep(1)  # 等待文件写入完成
    
  • 替换打印方式为win32print:os.startfile依赖系统关联程序打开PDF,稳定性不足。改用win32api.ShellExecute直接发送打印任务,可更好控制流程并捕获错误:
    import win32api
    import time
    
    def print_pdf(pdf_path, printer_name):
        try:
            win32api.ShellExecute(
                0,
                "printto",
                pdf_path,
                f'"{printer_name}"',
                ".",
                0
            )
            time.sleep(2)
        except Exception as e:
            print(f"打印失败: {str(e)}")
    
  • 修正PDF页面参数:当前设置bottomup=432属于非标准参数,可能导致打印机解析异常。建议移除该参数使用默认值,或用mm单位设置符合Rollo打印机的标准标签尺寸,比如landscape(100*mm, 63*mm)。
  • 减少重复资源调用:代码中两次调用client.open_by_url打开同一份表格,可改为只打开一次,降低API资源消耗:
    spreadsheet = client.open_by_url(sheet_url)
    label_sheet = spreadsheet.worksheet("Label")
    claims_sheet = spreadsheet.worksheet("Claims")
    
  • 添加错误捕获日志:在打印流程中加入try-except块,记录脚本执行时的异常信息,帮助定位偶发问题。

内容的提问来源于stack exchange,提问作者Anthony Madle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 02:20:24