Why am I getting a 'no such file or directory' error when importing images in tkinter using nuitka in Python?

huangapple go评论68阅读模式
英文:

Why am I getting a 'no such file or directory' error when importing images in tkinter using nuitka in Python?

问题

I am developing a tool in python with tkinter.
The structure of my project is the following:

  • project folder:
    • src
      • main.py
      • ...other files.py
      • changelog.md
    • res
      • img
        • images used by my project

In my main code I import several images in the following way:
question_icon = PhotoImage(file = "../res/img/question_icon_32.png")

When I try to build a one file executable with nuitka, if I execute it the \src folder then everything works, but if I try to move it to some other folder then I get this error when importing the images:

couldn't open "../res/img/question_icon_32.png": no such file or directory.

I figure the problem is the way I import the images, but I wasn't able to understand exactly what am I doing wrong.
I have python 3.11 and nuitka 1.5.8
I call nuitka with:
python -m nuitka --onefile --onefile-tempdir-spec="%TEMP%\onefile_%PID%_%TIME%" -o myprogram.exe --enable-plugin=tk-inter --include-data-dir="C:\...project_folder\res"=res --include-data-file="C:\...project_folder\src\changelog.md"=changelog.md C:\...project_folder\src\main.py

of course "C:...project_folder" is the full absolute path to the project folder.

Do you have any suggestion what am I doing wrong?

I thought the "../" was problematic so I tried putting the \res folder inside the \src folder and change the import to question_icon = PhotoImage(file = "/res/img/question_icon_32.png") but I still get the same error.

英文:

I am developing a tool in python with tkinter.
The structure of my project is the following:

  • project folder:
    • src
      • main.py
      • ...other files.py
      • changelog.md
    • res
      • img
        • images used by my project

In my main code I import several images in the following way:
question_icon = PhotoImage(file = "../res/img/question_icon_32.png")

When I try to build a one file executable with nuitka, if I execute it the \src folder then everything works, but if I try to move it to some other folder then I get this error when importing the images:

couldn't open "../res/img/question_icon_32.png": no such file or directory.

I figure the problem is the way I import the images, but I wasn't able to understand exactly what am I doing wrong.
I have python 3.11 and nuitka 1.5.8
I call nuitka with:
python -m nuitka --onefile --onefile-tempdir-spec="%TEMP%\onefile_%PID%_%TIME%" -o myprogram.exe --enable-plugin=tk-inter --include-data-dir="C:\...project_folder\res"=res --include-data-file="C:\...project_folder\src\changelog.md"=changelog.md C:\...project_folder\src\main.py

of course "C:...project_folder" is the full absolute path to the project folder.

Do you have any suggestion what am I doing wrong?

I thought the "../" was problematic so I tried putting the \res folder inside the \src folder and change the import to question_icon = PhotoImage(file = "/res/img/question_icon_32.png")
but I still get the same error

答案1

得分: 1

Nuitka 在主文件和被主文件包含的文件中处理相对导入的方式不同。我通过创建一个包装 .py 文件来解决这个问题,该文件只是调用我的主 .py 文件。然后,我的原始主函数中的所有相对路径都正常工作了。

更新:我已经了解到,Nuitka 处理与 .py 文件的相对路径与处理其他文件(如txt或其他数据文件,您的代码调用的文件)的方式不同。包装函数的解决方法可以解决 .py 文件的问题。当使用 --standalone 和非 .py 文件时,路径需要硬编码为 .dist 文件夹中的位置。(您还需要使用 --include 或复制文件到 .dist 文件夹中)。

英文:

Nuitka handles relative imports differently in the main file vs the files that get included by the main file. I've gotten around this by creating a wrapper .py that just calls my main .py. Then all my relative paths in my original main function worked properly.

Update: I've learned that Nuitka handles relative paths to .py files differently than for other files (such as txt or other data files that your code calls). The wrapper function hack fixes the problem for .py files. When using --standalone and non-py files, the paths need to be hard coded to the location in the .dist folder. (You also need to use --include or copy the files to the .dist folder.)

答案2

得分: 0

以下是您要翻译的内容:

当执行单个可执行文件时,它将在 nuitka 命令中指定的临时文件夹中运行,其中包括 nuitka 中包含的所有资源。我的问题是,此文件夹不尊重我的项目文件夹的相同结构,因此我需要修复导入资源的路径。

最终,我通过以下方式导入资源解决了问题:

question_icon = PhotoImage(file=resource_path("..\\res\\img\\question_icon_32.png"))

其中

def resource_path(relative_path):
    # 从相对路径中删除前缀..\。
    temp_folder_path_file = os.path.join(os.path.dirname(__file__), relative_path[3:])
    if os.path.isfile(temp_folder_path_file):
        return temp_folder_path_file
    else:
        return os.path.join(os.path.abspath('.'), relative_path)

请注意,我已经删除了 HTML 实体编码(如")以使代码更清晰。

英文:

When the single-file executable is executed, it will run in a temp folder specified in the nuitka command, which will include all the resourced included in nuitka. My problem was that this folder do not respect the same structure of my project folder, therefore I needed to fix the path to import the resources.

I eventually solved by importing the resources like this:

    question_icon = PhotoImage(file = resource_path("..\\res\\img\\question_icon_32.png"))

where

enter code here
def resource_path(relative_path):

   # The prefix ..\ is removed from the relative path
   temp_folder_path_file = os.path.join(os.path.dirname(__file__), relative_path[3:])
   if os.path.isfile(temp_folder_path_file):
       return temp_folder_path_file
   else:
       return os.path.join(os.path.abspath('.'), relative_path)

huangapple
  • 本文由 发表于 2023年5月25日 18:59:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331552.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定