Python条码打印脚本IDLE运行正常,PyInstaller打包后无法生成条码
问题:PyInstaller打包条码工具后无法生成条码(OSError: cannot open resource)
我几乎没编程经验,靠GPT4写了个库存管理用的条码打印工具,功能是生成Code39条码,每次打印编号自动加1。脚本在IDLE里运行正常,但用PyInstaller打包后没法生成条码图片,CMD里抛出「OSError: cannot open resource」错误。脚本能正常生成last_number.txt和barcodes文件夹,但条码生成失败,以下是完整代码和报错栈信息:
完整代码
import tkinter as tk from barcode import Code39 from barcode.writer import ImageWriter from PIL import Image, ImageFont, ImageDraw import sys import os import time import threading def resource_path(relative_path): try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) font_path = resource_path('resources/ARLRDBD.ttf') def get_next_number(filename): try: with open(filename, 'r') as f: lines = f.read().splitlines() # splitlines method strips newline characters last_number = int(lines[-1]) except FileNotFoundError: last_number = 54999 # start from 55000 next_number = last_number + 1 with open(filename, 'a') as f: f.write(f"{next_number}\n") # append the next number to the file return last_number, next_number def generate_barcode(number): code39 = Code39(str(number), writer=ImageWriter(), add_checksum=False) # Create the directory if it does not exist directory = 'barcodes' if not os.path.exists(directory): os.makedirs(directory) filename = os.path.join(directory, f"barcode_{number}.jpeg") # Save the file in the directory barcode_img = code39.save(filename) img = Image.open(barcode_img) width_mm = 62 height_mm = 29 width_pixel = int(width_mm * (300 / 25.4)) height_pixel = int(height_mm * (300 / 25.4)) img_resized = img.resize((width_pixel, height_pixel)) draw = ImageDraw.Draw(img_resized) font = ImageFont.load_default() text_bbox = draw.textbbox((0, 0), str(number), font=font) text_width = text_bbox[2] x_position = (img_resized.width - text_width) / 2 draw.text((x_position, img_resized.height - 50), str(number), font=font, fill=255) img_resized.save(barcode_img) return barcode_img def print_file(barcode_img): time.sleep(1) # let the system recognize the new file os.startfile(barcode_img, 'print') threading.Timer(60, os.remove, [barcode_img]).start() # delay before deleting the file def main(): last_number, next_number = get_next_number("last_number.txt") barcode_img = generate_barcode(next_number) print_file(barcode_img) # Adding 1 to the numbers displayed in the labels last_label.config(text="Last: " + str(last_number + 1)) next_label.config(text="Next: " + str(next_number + 1)) root = tk.Tk() root.geometry('400x400') # Set the window size to 400x400 root.title("Auction Barcode Print Button") # Set the window title # Create the labels with default text last_label = tk.Label(root, text="Last: ", font=('Arial', 14)) next_label = tk.Label(root, text="Next: ", font=('Arial', 14)) # Place the labels in the window last_label.pack(pady=(50, 10)) next_label.pack(pady=(10, 20)) button_frame = tk.Frame(root, width=200, height=200) # Frame to hold the button button_frame.pack_propagate(0) # prevents the frame to shrink button_frame.pack(pady=(20,20)) button = tk.Button(button_frame, text="Print Barcode", command=main, relief=tk.RAISED) button.pack(fill=tk.BOTH, expand=1) # Button fills the entire frame root.mainloop()
报错信息
Exception in Tkinter callback Traceback (most recent call last): File "tkinter\__init__.py", line 1948, in __call__ File "Auction_Label_4.py", line 72, in main File "Auction_Label_4.py", line 42, in generate_barcode File "barcode\base.py", line 65, in save File "barcode\codex.py", line 74, in render File "barcode\base.py", line 105, in render File "barcode\writer.py", line 265, in render File "barcode\writer.py", line 439, in _paint_text File "PIL\ImageFont.py", line 1008, in truetype File "PIL\ImageFont.py", line 1005, in freetype File "PIL\ImageFont.py", line 255, in __init__ OSError: cannot open resource
解决办法
1. 给条码生成器指定字体路径
报错根源是barcode库生成条码文本时找不到字体。你已经定义了font_path但没在条码生成环节使用,修改generate_barcode函数,给ImageWriter配置字体:
def generate_barcode(number): # 添加字体配置 writer_options = { 'font_path': font_path, 'font_size': 12 # 可根据需求调整字号 } code39 = Code39(str(number), writer=ImageWriter(), add_checksum=False) code39.writer.set_options(writer_options) # 应用配置 # 剩余代码保持不变...
2. 确保PyInstaller打包时包含字体文件
打包时需要把resources/ARLRDBD.ttf一起打包进程序,执行PyInstaller命令时加上--add-data参数:
Windows系统:
pyinstaller --onefile --add-data "resources/ARLRDBD.ttf;resources" Auction_Label_4.py
macOS/Linux系统:
pyinstaller --onefile --add-data "resources/ARLRDBD.ttf:resources" Auction_Label_4.py
3. 备选方案:使用系统默认字体(兼容性较差)
如果不想打包字体,也可以指定系统已有的字体名称(比如Arial),但不同系统的字体名称可能不一致,容易出问题:
writer_options = { 'font': 'Arial', 'font_size': 12 }
为什么IDLE运行正常?
IDLE运行时用的是本地系统环境,barcode库能自动找到系统默认字体;但PyInstaller打包后会创建一个独立的临时运行环境,无法访问系统默认字体路径,必须显式指定字体文件位置。
内容的提问来源于stack exchange,提问作者Shaken89
相关产品推荐
相关产品推荐

