使用 pyinstaller 打包的应用程序不会从临时目录(tkinter、tksvg、tempfile)打开文件

问题描述 投票:0回答:3

大家好,我对一个包含 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。和他们在一起?

python tkinter pyinstaller temporary-files
3个回答
1
投票

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 在哪里找到您想要“获取”的任何文件


1
投票

一段时间后,发现将 --collect-all="tksvg" 添加到 pyinstaller 就足够了。也许你可以更具体地说明编译包中缺少的内容,但我没有能力判断它,所以我选择了安全的全部收集。 谢谢


0
投票

使用添加数据或编辑您的规范文件将 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 都不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.