Tkinter发票生成器转exe后报错:找不到模板文件
问题现象
- 基于Tkinter开发的发票生成器,
.py脚本本地运行正常,但打包成.exe后抛出PackageNotFoundError,提示无法找到Template/invoice_template.docx文件
错误日志
Exception in Tkinter callback
Traceback (most recent call last):
File "tkinter_init_.py", line 1921, in call
File "Bill.py", line 62, in generate
File "docxtpl\template.py", line 359, in render
File "docxtpl\template.py", line 52, in render_init
File "docxtpl\template.py", line 48, in init_docx
File "docx\api.py", line 23, in Document
File "docx\opc\package.py", line 116, in open
File "docx\opc\pkgreader.py", line 22, in from_file
File "docx\opc\phys_pkg.py", line 21, in new
docx.opc.exceptions.PackageNotFoundError: Package not found at 'Template/invoice_template.docx'
项目路径结构
Bill System: \__Template \__invoice_template.docx \__Bill.py
相关代码片段
# Get the absolute path to the 'Template' folder template_folder = os.path.abspath('Template') # Construct the full path to the template file template_file_path = os.path.join(template_folder, 'invoice_template.docx') def generate(): doc = DocxTemplate(template_file_path) name = namebox.get() place = placebox.get() phone = phbox.get() subtotal = sum(item[3] for item in invoice_list) salestax = 0.1 total = subtotal*(1-salestax) doc.render({"name":name, "place":place, "phone":phone, "invoice_list": invoice_list, "subtotal":subtotal, "salestax":str(salestax*100)+"%", "total":total}) doc_name = name + datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S") + ".docx" doc.save(doc_name)
分步解决方案
1. 修正路径获取逻辑(核心)
打包成exe后,程序会在系统临时目录运行,而非原项目目录。需通过sys._MEIPASS获取exe解压后的临时路径:
import os import sys def get_template_path(): # 判断是否为打包后的exe环境 if hasattr(sys, '_MEIPASS'): base_path = sys._MEIPASS else: # 开发环境下取当前脚本所在目录 base_path = os.path.dirname(os.path.abspath(__file__)) return os.path.join(base_path, 'Template', 'invoice_template.docx') # 替换原路径赋值代码 template_file_path = get_template_path()
2. 打包时包含模板文件(以PyInstaller为例)
执行打包命令时,需指定将模板文件加入打包资源,确保exe能读取到:
pyinstaller --onefile --add-data "Template/invoice_template.docx;Template" Bill.py
- 参数说明:
--onefile:生成单个exe文件--add-data:Windows用分号分隔源/目标路径,Linux/macOS用冒号,将模板文件打包后放到exe解压目录的Template子文件夹中
3. 调试路径(可选)
添加路径输出代码,确认实际获取的路径是否正确:
print(f"模板文件实际路径:{template_file_path}")
打包后运行exe,查看控制台输出的路径是否符合预期。
4. 测试打包程序
将生成的exe文件放在任意目录运行,尝试生成发票,验证模板文件能否正常读取。
内容的提问来源于stack exchange,提问作者Devaraj Murugan

