Pyinstaller OneFile可以访问外部资源

发布于 2025-01-30 06:57:28 字数 1607 浏览 3 评论 0原文

我是Python的新手,我需要一些基本内容的帮助。我写了一个我想要转换为.exe的小程序。如果我与Python一起运行,该程序正常工作。

但是,当我使用Pyinstaller时,我无法访问外部资源。 我的目标是将MyProgram.exe与资产文件夹相同的目录中。资产文件夹包含图像和一个iW/r ...的json文件...

我正在使用的命令就是这样,而没有其他配置:

pyinstaller --onefile --name myprogram gui.py

因此,对于代码,我有这样的代码:

OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path("./assets")

def relative_to_assets(path: str) -> Path:
    return ASSETS_PATH / Path(path)

使用:

canvas.place(x = 0, y = 0)
    image_image_1 = PhotoImage(
    file=relative_to_assets("image_1.png"))
image_1 = canvas.create_image(
    225.0,
    114.0,
    image=image_image_1
)

并加载/读取JSON文件:

def loadJSONFile():
data = {}
if os.path.isfile(relative_to_assets("data.json")) and os.access(ASSETS_PATH, os.R_OK):
    WALLETSLISTFILE = open(relative_to_assets("data.json"),"r")
    data = json.loads(WALLETSLISTFILE.read())
else:
    print("Either file is missing or is not readable, creating file...")
    with io.open(os.path.join(ASSETS_PATH, 'data.json'), 'w') as db_file:
        db_file.write(json.dumps({}))
    WALLETSLISTFILE = open(relative_to_assets("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
return data

使用Python(有效)的项目结构:

”在此处输入图像描述”

因此,我想要的是用-Onefile生成gui.exe,然后在同一.exe目录中加入文件夹“资产”。

但是,由于该代码上方的文件路径是不正确的,并且程序没有启动(因为我现在没有处理异常)

I'm very new to Python and I need help with some basic stuff. I wrote a small program that I want do convert to .exe. The program works fine if I run it with Python.

But when I use pyinstaller I can't access external resources.
My goal is to have myprogram.exe in the same directory as an assets folder. The assets folder contains images and a json file that I W/R ...

The command I'm using is just this, and no other config:

pyinstaller --onefile --name myprogram gui.py

So for the code I have this:

OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path("./assets")

def relative_to_assets(path: str) -> Path:
    return ASSETS_PATH / Path(path)

Using like so:

canvas.place(x = 0, y = 0)
    image_image_1 = PhotoImage(
    file=relative_to_assets("image_1.png"))
image_1 = canvas.create_image(
    225.0,
    114.0,
    image=image_image_1
)

And to load/read the JSON file:

def loadJSONFile():
data = {}
if os.path.isfile(relative_to_assets("data.json")) and os.access(ASSETS_PATH, os.R_OK):
    WALLETSLISTFILE = open(relative_to_assets("data.json"),"r")
    data = json.loads(WALLETSLISTFILE.read())
else:
    print("Either file is missing or is not readable, creating file...")
    with io.open(os.path.join(ASSETS_PATH, 'data.json'), 'w') as db_file:
        db_file.write(json.dumps({}))
    WALLETSLISTFILE = open(relative_to_assets("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
return data

Project Structure with python (which works):

enter image description here

So what I want is to generate the gui.exe with --onefile and later join the folder "assets" in same .exe directory.

But with that code above the path to the files is incorrect and the program doesn´t starts (because I'm not handling the exception right now)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我最亲爱的 2025-02-06 06:57:28

因此,要回答我自己的问题,我将有关JSON文件的IO操作的代码更改为JSON文件,并在将Pyinstaller用于其他资源时添加了一些选项。

因此,关于pyinstaller:

pyinstaller --onefile --name "gui" --add-data "assets/*.png;./assets" --add-data "assets/*.ico;./assets" gui.py

因此,当使用Pyinstaller生成的.exe并使用以下路径定义时:

OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path("./assets")

def relative_to_assets(path: str) -> Path:
   return ASSETS_PATH / Path(path)

canvas.place(x = 0, y = 0)
   image_image_1 = PhotoImage(
      file=relative_to_assets("image_1.png"))
      image_1 = canvas.create_image(
      225.0,
      114.0,
      image=image_image_1
)

我的资产存储在temp文件夹中:

C:\Users\username\AppData\Local\Temp\_MEI89482\assets

对于静态资源(如图像和文件),只能读取,因为当程序关闭时,临时文件夹也消失了。

因此,对于我的JSON文件,我必须将路径更改为更持久的位置。因此,我使用了AppData OS Env。 var。,就像这样:

import os

APPDATA_PATH = os.environ['APPDATA']
PROGRAM_FOLDER = 'MyData'

def relative_to_appdata_folder():
    return os.path.join(APPDATA_PATH,PROGRAM_FOLDER)

def relative_to_json_file(path: str) -> Path:
    return relative_to_appdata_folder() / Path(path)

def loadJSONFile():
    data = {}
    if os.path.isfile(relative_to_json_file("data.json")) and 
os.access(relative_to_appdata_folder(), os.R_OK):
    WALLETSLISTFILE = open(relative_to_json_file("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
else:
    print("Either file is missing or is not readable, creating file...")
    with io.open(os.path.join(relative_to_appdata_folder(), 'data.json'), 'w') as db_file:
        db_file.write(json.dumps({}))
    WALLETSLISTFILE = open(relative_to_json_file("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
return data

我还需要检查目录是否在上一个路径中确实创建文件“ data.json”:

if not os.path.exists(relative_to_appdata_folder()):
    os.makedirs(relative_to_appdata_folder())

所以这就是我使它工作的方式,并且我的data.json文件存储在这里:

C:\Users\username\AppData\Roaming\MyData

如果有人更优雅的解决方案让我知道,我喜欢学习更多。

So to answear to my own question I changed my code regarding to the IO operations for the JSON file and added a few options when using pyinstaller for the other resources.

So regarding to pyinstaller:

pyinstaller --onefile --name "gui" --add-data "assets/*.png;./assets" --add-data "assets/*.ico;./assets" gui.py

So when using the .exe generated by pyinstaller and using these path definitions:

OUTPUT_PATH = Path(__file__).parent
ASSETS_PATH = OUTPUT_PATH / Path("./assets")

def relative_to_assets(path: str) -> Path:
   return ASSETS_PATH / Path(path)

canvas.place(x = 0, y = 0)
   image_image_1 = PhotoImage(
      file=relative_to_assets("image_1.png"))
      image_1 = canvas.create_image(
      225.0,
      114.0,
      image=image_image_1
)

My assets are stored in a temp folder:

C:\Users\username\AppData\Local\Temp\_MEI89482\assets

That´s ok for static resources like images and files to only read, because when the program closes the temp folder also goes away.

So to my JSON file I had to change the Path to a more persistent location. So I used the APPDATA OS env. var., like so:

import os

APPDATA_PATH = os.environ['APPDATA']
PROGRAM_FOLDER = 'MyData'

def relative_to_appdata_folder():
    return os.path.join(APPDATA_PATH,PROGRAM_FOLDER)

def relative_to_json_file(path: str) -> Path:
    return relative_to_appdata_folder() / Path(path)

def loadJSONFile():
    data = {}
    if os.path.isfile(relative_to_json_file("data.json")) and 
os.access(relative_to_appdata_folder(), os.R_OK):
    WALLETSLISTFILE = open(relative_to_json_file("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
else:
    print("Either file is missing or is not readable, creating file...")
    with io.open(os.path.join(relative_to_appdata_folder(), 'data.json'), 'w') as db_file:
        db_file.write(json.dumps({}))
    WALLETSLISTFILE = open(relative_to_json_file("data.json"), "r")
    data = json.loads(WALLETSLISTFILE.read())
return data

Also I needed to check if the directory exists do create the file "data.json" in the previous Path:

if not os.path.exists(relative_to_appdata_folder()):
    os.makedirs(relative_to_appdata_folder())

So that's how I got it to work and my data.json file is stored here:

C:\Users\username\AppData\Roaming\MyData

If anyone has a more elegant solution let me know, I love to learn more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文