Pyinstaller如何添加数据文件

54

我在使用pyinstaller时遇到了困难。每当我尝试使用带有kivy GUI和.kv文件的特定脚本进行构建,并在构建后运行.exe文件时,都会出现致命错误:

IOError: [Errno 2] No such file or directory: 'main.kv'

我尝试使用--add-data添加.kv文件以及mdb和dsn文件(用于pypyodbc),但是我收到了一个错误:未识别的参数:--add-data'main.kv'。(还有其他关于所提到的其他文件的--add-data参数。)

是否有任何解决方案或者替代方法?

5个回答

98

正如其他人(@Anson Chan, @schlimmchen)所说:

如果您想添加一些额外的文件,应该使用添加数据文件

两种实现方式

  • 命令行:将参数添加到--add-data
  • Spec文件:将参数添加到datas=
    • 在第一次运行pyinstaller时生成。
      • 然后稍后可以编辑您的*.spec文件。
      • 然后运行pyinstaller将直接使用您的*.spec文件。

Parameter逻辑

--add-datadatas=中的参数:

  • --add-data:
    • 格式: {source}{os_separator}{destination}
      • os_separator:
        • Windows: ;
        • Mac/Linux/Unix: :
      • sourcedestination
        • 逻辑:
          • source: 单个或多个文件的路径,支持glob语法。告诉PyInstaller在哪里找到文件。
          • destination 文件或文件夹: 在运行时包含源文件的目标文件夹。 * 注意: 不是目标文件名。
            • 文件夹: 目标文件夹路径,这是相对的目标根目录,而不是绝对路径。
    • 示例:
      • 单个文件: 'src/README.txt:.'
      • 多个文件: '/mygame/sfx/*.mp3:sfx'
      • 文件夹: '/mygame/data:data'
  • datas=
    • 格式: 列表或元组。
    • 示例: 请参见以下内容。
added_files = [
    ( 'src/README.txt', '.' ),
    ( '/mygame/data', 'data' ),
    ( '/mygame/sfx/*.mp3', 'sfx' )
]

a = Analysis(...
    datas = added_files,
    ...
)

您的情况

对于您的(Windows操作系统),这是:

  • 在命令行中使用--add-data 参数
    • pyinstaller -F --add-data "main.kv;." yourtarget.py

或者:

  • datas=yourtarget.spec 文件中,如下所示:
a = Analysis(...
    datas = ["main.kv", "."],
    ...
)

7
这是一个非常好的答案,清楚地展示了命令行参数和规范文件等价项之间的对应关系。示例很棒。做得好! - bearcat
如果有人需要帮助,我在这里分享一下我的经验。我的情况是将chromedriver.exe存储在资源文件夹中。我的命令--add-data行如下:--add-data 'src\resources\chromedriver.exe;resources.' 这样就会将一个资源文件夹添加到临时MEIPASS文件夹中,模仿我的实际目录。 - Nick08

61

如果您需要帮助,请检查 pyinstaller -h 命令,您会发现 --add-data 的用法是这样的 [--add-data <SRC;DEST or SRC:DEST>]。因此在您的情况下,请尝试使用:

pyinstaller -F --add-data "main.kv;main.kv" yourtarget.py

38
在分隔符上是使用分号还是冒号,取决于os.pathsep,即在大多数*nix系统上,这是一个冒号,在Windows上应该是一个分号。 - schlimmchen
1
关于输出 dist/ 文件夹,main.kv 文件在哪里? - bw4sz
1
PyInstaller文档可能需要更清晰的说明...我找到的所有示例都使用了:...通常我只在spec文件中执行此操作,但我真的不想为此项目创建一个spec文件。 - Joran Beasley
11
以上代码会在分发路径下添加一个文件夹,并将 main.kv 放置其中,路径应为:distfolder/main/main.kv。为了解决这个问题,应将命令改为:pyinstaller -F --add-data "main.kv;." yourtarget.py - Spencer
1
在我看来,@Spencer的评论是这个答案的一个重要部分,目前这个答案的表述有些误导。 - Mark Ch

9
解决方案是运行:pyi-makespec yourscript.py,然后编辑yourscript.spec脚本,在a=Analysis下的datas中添加文件。
datas=[ ( '/pathToYourFile/main.kv', '.' )]

然后运行pyinstaller yourscript.spec,之后应该就可以了。


@HarshitAgrawal 在逗号后添加: datas=[('/pathToYourFile/main.kv', '.')], - Pavel M.
@pmus 我尝试使用逗号,但仍然无效,并且在运行.exe文件时显示相同的错误“太多值无法解包”错误。 - HarshitMadhav
1
对于未来的用户,如果你得到了“too many values to unpack”的错误,请确保将你的路径以元组形式添加到列表中,例如:('source\dir', 'destination\dir')。当我第一次阅读答案时,我错过了这个细节,并且也遇到了“too many values”错误。 - Brandon Barney
在添加自己的图像文件到包中后,我遇到了与@BrandonBarney相反的情况 - Too few values to unpack。在查看由我的自动生成的.spec文件生成的a.datas的内容后,我发现每个元组都有一个额外的字符串“'DATA'”...所以我不得不使用:a.datas += [('assets/icon.ico', 'assets/icon.ico', 'DATA')]这在文档中似乎不是最新的。 - tdpu
在规范文件中,有什么可以添加的内容相当于命令行中的--onefile选项? - fishbacp

3
下一步 - 运行 PyInstaller 时,假定使用 -F 或 --onefile 选项。
请注意(此处为 MacOS Monterey 12.2),您的 .app 文件中预期的文件夹层次结构将类似于以下内容:

expected_folder_hierarchy

Pyinstaller不会向此文件夹结构中的任何文件夹添加文件或创建必要的文件夹,至少不会以任何明显的方式。您找不到它们。
但是,当应用程序运行时,将在/var/folders下使用一个临时文件夹,这与上面第1点中的文件夹结构非常不同。在运行应用程序时,print(os.path.dirname(__file__))将显示每次运行时使用的确切临时文件夹。为方便起见,我们称之为my_app_tmp_folder,即您的应用程序在文件夹/var/folder/my_app_tmp_folder下运行。
然后,pyinstaller会在此临时文件夹中添加数据文件或创建必要的目录。换句话说,当应用程序运行时,所有添加的文件都将在其中,并按照指定的文件夹结构(通过--add-data选项)进行。 print(os.listdir(os.path.dirname(__file__)))将显示系统和应用程序所需的文件和文件夹。
底线:使用--add-data选项指定的文件将在运行时显示在/var/folder/my_app_tmp_folder中,而不是在*.app文件夹中。
一些有用的文档链接:

https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#using-file

https://pyinstaller.readthedocs.io/en/stable/spec-files.html#adding-files-to-the-bundle

https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#bundling-to-one-file


-1

我的应用程序出现了这个问题,以及一个随后的问题,如果不是必然的话,那么很可能会出现。

1. --add-data 用于 kv 文件

使用 crifan 的答案中提到的 --add-data

2. Kivy 仍然找不到文件

一旦 PyInstaller 将 kv 文件放在正确的目录中,Kivy 仍然无法找到该文件。

可能的症状:

  • GUI 启动,但屏幕是 黑色和空白
  • 一个依赖于应用程序代码的 AttributeError 错误。

AttributeError 示例:

  • 这个问题

  • 我的情况:

    AttributeError: 'NoneType' object has no attribute 'ids'

幸运的是,这个答案解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接