大家好,我对一个包含 pyinstaller 的简单应用程序(至少 MRE 很简单)有疑问。 这个桌面应用程序应该显示一个简单的 SVG 文件(我使用 tksvg)。 我的应用程序首先将 SVG 写入临时目录(写入不像 MRE 那样简单),然后在适当的时候显示它。它工作得很好,直到我用 pyinstaller 打包它。 我的完整应用程序控制台向我抛出无法找到该文件的错误。该路径始终以 ksvg 结尾。并且这样的目录不存在。 看起来 tksvg 会创建这样的子文件夹,但 pyinstaller 缺少这样的指令? 我能做什么有什么想法吗? 警告,完全菜鸟。 谢谢
from tkinter import *
import tempfile
import tksvg
root = Tk()
temp_dir = tempfile.TemporaryDirectory()
print(temp_dir.name)
with open(temp_dir.name + f'\\test.svg', 'w') as a_file:
a_file.write('<svg viewBox="0 0 400 400"><rect x="0" y="0" width="400" height="400" fill="red" /></svg>')
svg_image = tksvg.SvgImage(file=temp_dir.name + f'\\test.svg')
show_svg = Label(root, image=svg_image)
show_svg.pack()
mainloop()
编辑
经过一番与这个主题的斗争,我确信这一定是 pyinstaller 如何打包库的问题,特别是 tksvg。 @JRiggles 提出的方法本身有效,但不适用于 tksvg 对象,在我的情况下没有必要(我使用临时目录来管理文件)。 为了检查临时目录在打包(pyinstaller)时是否也能工作,我创建了“jpeg reader”脚本,即使使用 PIL 库,它也能完美工作。
from tkinter import *
import tempfile
from tkinter import filedialog
from PIL import Image, ImageTk
root = Tk()
temp_dir = tempfile.TemporaryDirectory()
print(temp_dir.name) # just to check if temp. dir. was created
jpeg_file = filedialog.askopenfilename(filetypes=[("jpeg file", "*.jpeg")]) # opening file from disc
picture = Image.open(jpeg_file) # reading it with PIL library
picture.save(temp_dir.name+'\\test.jpeg') # saving image to temp. dir.
an_image = Image.open(temp_dir.name + '\\test.jpeg') # opening image from temp.dir.
the_image = ImageTk.PhotoImage(an_image) # reading image
show_image = Label(root, image=the_image) # setting label as "display"
show_image.pack() # showing the image
mainloop()
有没有人有 SVG 库、tksvg 或任何其他库的经验,以及如何制作 exe。和他们在一起?
Pyinstaller 将您的资源(图像、图标等)放置在运行时在临时目录中创建的特殊目录中。我使用这个
fetch_resource
函数在运行 pyinstaller 可执行文件时动态加载资源
import sys
from pathlib import Path
def fetch_resource(rsrc_path):
"""Loads resources from the temp dir used by pyinstaller executables"""
try:
base_path = Path(sys._MEIPASS)
except AttributeError:
return rsrc_path # not running as exe, just return the unaltered path
else:
return base_path.joinpath(rsrc_path)
在你的情况下,你会像这样使用它:
svg_path = fetch_resource(r'path\to\test.svg')
with open(svg_path, 'w') as a_file:
...
svg_image = tksvg.SvgImage(file=svg_path)
您需要使用
--add-data
命令行 或 通过将路径添加到 datas
文件中的 *.spec
列表来告诉 pyinstaller 在哪里找到您想要“获取”的任何文件
一段时间后,发现将 --collect-all="tksvg" 添加到 pyinstaller 就足够了。也许你可以更具体地说明编译包中缺少的内容,但我没有能力判断它,所以我选择了安全的全部收集。 谢谢
使用添加数据或编辑您的规范文件将 tksvg 包添加到您的 dist 文件夹中。
例如:
pyinstaller --onedir --w add-data= 'env/Lib/site-packages/tksvg/*';'tksvg' myscript.py
或
例如:在规格文件中
datas = ['env/Lib/site-packages/tksvg/*','tksvg']
这对我有用。您甚至可以简单地复制 tksvg 包文件夹并将其粘贴到 dist 文件夹中。
在我尝试此操作之前,隐藏导入或将包路径添加到 pathex 都不起作用。