使用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
相关产品推荐
相关产品推荐

