简体   繁体   English

使用 PyInstaller (--onefile) 捆绑数据文件

[英]Bundling data files with PyInstaller (--onefile)

I'm trying to build a one-file EXE with PyInstaller which is to include an image and an icon.我正在尝试使用 PyInstaller 构建一个包含图像和图标的单文件 EXE。 I cannot for the life of me get it to work with --onefile .我一辈子都无法让它与--onefile一起工作。

If I do --onedir it works all works very well.如果我这样做--onedir一切都很好。 When I use --onefile , it can't find the referenced additional files (when running the compiled EXE).当我使用--onefile时,它找不到引用的附加文件(运行编译的 EXE 时)。 It finds the DLLs and everything else fine, just not the two images.它发现 DLL 和其他一切都很好,只是不是两个图像。

I've looked in the temp-dir generated when running the EXE ( \Temp\_MEI95642\ for example) and the files are indeed in there.我查看了运行 EXE 时生成的临时目录(例如\Temp\_MEI95642\ ),文件确实在那里。 When I drop the EXE in that temp-directory it finds them.当我将 EXE 放入该临时目录时,它会找到它们。 Very perplexing.很费解。

This is what I've added to the .spec file这是我添加到.spec文件中的内容

a.datas += [('images/icon.ico', 'D:\\[workspace]\\App\\src\\images\\icon.ico',  'DATA'),
('images/loaderani.gif','D:\\[workspace]\\App\\src\\images\\loaderani.gif','DATA')]     

I should add that I have tried not putting them in subfolders as well, didn't make a difference.我应该补充一点,我也尝试过不将它们放在子文件夹中,但没有任何区别。

Edit: Marked newer answer as correct due to PyInstaller update.编辑:由于 PyInstaller 更新,将较新的答案标记为正确。

Newer versions of PyInstaller do not set the env variable anymore, so Shish's excellent answer will not work.较新版本的 PyInstaller 不再设置env变量,因此 Shish 的出色答案将不起作用。 Now the path gets set as sys._MEIPASS :现在路径设置为sys._MEIPASS

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

pyinstaller unpacks your data into a temporary folder, and stores this directory path in the _MEIPASS2 environment variable. pyinstaller 将您的数据解压到一个临时文件夹中,并将此目录路径存储在_MEIPASS2环境变量中。 To get the _MEIPASS2 dir in packed-mode and use the local directory in unpacked (development) mode, I use this:要在打包模式下获取_MEIPASS2目录并在解包(开发)模式下使用本地目录,我使用以下命令:

def resource_path(relative):
    return os.path.join(
        os.environ.get(
            "_MEIPASS2",
            os.path.abspath(".")
        ),
        relative
    )

Output:输出:

# in development
>>> resource_path("app_icon.ico")
"/home/shish/src/my_app/app_icon.ico"

# in production
>>> resource_path("app_icon.ico")
"/tmp/_MEI34121/app_icon.ico"

All of the other answers use the current working directory in the case where the application is not PyInstalled (ie sys._MEIPASS is not set).在应用程序不是 PyInstalled(即sys._MEIPASS未设置)的情况下,所有其他答案都使用当前工作目录 That is wrong, as it prevents you from running your application from a directory other than the one where your script is.这是错误的,因为它会阻止您从脚本所在的目录以外的目录运行应用程序。

A better solution:更好的解决方案:

import sys
import os

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

Perhaps i missed a step or did something wrong but the methods which are above, didn't bundle data files with PyInstaller into one exe file.也许我错过了一个步骤或做错了什么,但是上面的方法没有将 PyInstaller 的数据文件捆绑到一个 exe 文件中。 Let me share the steps what i have done.让我分享我所做的步骤。

  1. step:Write one of the above methods into your py file with importing sys and os modules.步骤:通过导入 sys 和 os 模块将上述方法之一写入您的 py 文件。 I tried both of them.我试过他们两个。 The last one is:最后一个是:

     def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)
  2. step: Write, pyi-makespec file.py , to the console, to create a file.spec file.步骤:将pyi-makespec file.py写入控制台,创建file.spec文件。

  3. step: Open, file.spec with Notepad++ to add the data files like below:步骤:使用 Notepad++ 打开 file.spec 以添加如下数据文件:

     a = Analysis(['C:\\\\Users\\\\TCK\\\\Desktop\\\\Projeler\\\\Converter-GUI.py'], pathex=['C:\\\\Users\\\\TCK\\\\Desktop\\\\Projeler'], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher) #Add the file like the below example a.datas += [('Converter-GUI.ico', 'C:\\\\Users\\\\TCK\\\\Desktop\\\\Projeler\\\\Converter-GUI.ico', 'DATA')] pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True, name='Converter-GUI', debug=False, strip=False, upx=True, #Turn the console option False if you don't want to see the console while executing the program. console=False, #Add an icon to the program. icon='C:\\\\Users\\\\TCK\\\\Desktop\\\\Projeler\\\\Converter-GUI.ico') coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='Converter-GUI')
  4. step: I followed the above steps, then saved the spec file.步骤:我按照上面的步骤,然后保存了spec文件。 At last opened the console and write, pyinstaller file.spec (in my case, file=Converter-GUI).最后打开控制台并写入, pyinstaller file.spec (在我的情况下,file=Converter-GUI)。

Conclusion: There's still more than one file in the dist folder.结论:dist 文件夹中还有不止一个文件。

Note: I'm using Python 3.5.注意:我使用的是 Python 3.5。

EDIT: Finally it works with Jonathan Reinhart's method.编辑:最后它适用于乔纳森莱因哈特的方法。

  1. step: Add the below codes to your python file with importing sys and os.步骤:通过导入 sys 和 os 将以下代码添加到您的 python 文件中。

     def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)
  2. step: Call the above function with adding the path of your file:步骤:通过添加文件路径调用上述函数:

     image_path = resource_path("Converter-GUI.ico")
  3. step: Write the above variable that call the function to where your codes need the path.步骤:将调用函数的上述变量写入代码需要路径的位置。 In my case it's:就我而言,它是:

     self.window.iconbitmap(image_path)
  4. step: Open the console in the same directory of your python file, write the codes like below:步骤:在你的python文件的同目录下打开控制台,编写如下代码:

     pyinstaller --onefile your_file.py
  5. step: Open the .spec file of the python file and append the a.datas array and add the icon to the exe class, which was given above before the edit in 3'rd step.步骤:打开python文件的.spec文件并附加a.datas数组并将图标添加到exe类中,这是在第3步编辑之前给出的。
  6. step: Save and exit the path file.步骤:保存并退出路径文件。 Go to your folder which include the spec and py file.转到包含规范和 py 文件的文件夹。 Open again the console window and type the below command:再次打开控制台窗口并输入以下命令:

     pyinstaller your_file.spec

After the 6. step your one file is ready to use. 6. 步骤之后,您的一个文件就可以使用了。

Instead for rewriting all my path code as suggested, I changed the working directory:我没有按照建议重写所有路径代码,而是更改了工作目录:

if getattr(sys, 'frozen', False):
    os.chdir(sys._MEIPASS)

Just add those two lines at the beginning of your code, you can leave the rest as is.只需在代码的开头添加这两行,其余部分就可以了。

I have been dealing with this issue for a long(well, very long) time.我一直在处理这个问题长一段时间(好吧,长时间)。 I've searched almost every source but things were not getting in a pattern in my head.我几乎搜索了所有来源,但事情并没有在我脑海中形成模式。

Finally, I think I have figured out exact steps to follow, I wanted to share.最后,我想我已经找到了要遵循的确切步骤,我想分享一下。

Note that, my answer uses information on the answers of others on this question.请注意,我的回答使用了其他人对此问题的回答的信息。

How to create a standalone executable of a python project.如何创建 python 项目的独立可执行文件。

Assume, we have a project_folder and the file tree is as follows:假设我们有一个project_folder,文件树如下:

 project_folder/ main.py xxx.py # another module yyy.py # another module sound/ # directory containing the sound files img/ # directory containing the image files venv/ # if using a venv

First of all, let's say you have defined your paths to sound/ and img/ folders into variables sound_dir and img_dir as follows:首先,假设您已将sound/img/文件夹的路径定义为变量sound_dirimg_dir ,如下所示:

img_dir = os.path.join(os.path.dirname(__file__), "img")
sound_dir = os.path.join(os.path.dirname(__file__), "sound")

You have to change them, as follows:您必须更改它们,如下所示:

img_dir = resource_path("img")
sound_dir = resource_path("sound")

Where, resource_path() is defined in the top of your script as:其中, resource_path()在脚本顶部定义为:

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

Activate virtual env if using a venv,如果使用 venv,请激活虚拟 env,

Install pyinstaller if you didn't yet, by: pip3 install pyinstaller .如果您还没有安装 pyinstaller,请通过: pip3 install pyinstaller

Run: pyi-makespec --onefile main.py to create the spec file for the compile and build process.运行: pyi-makespec --onefile main.py为编译和构建过程创建规范文件。

This will change file hierarchy to:这会将文件层次结构更改为:

 project_folder/ main.py xxx.py # modules xxx.py # modules sound/ # directory containing the sound files img/ # directory containing the image files venv/ # if using a venv main.spec

Open(with an edior) main.spec :打开(使用编辑器) main.spec

At top of it, insert:在它的顶部,插入:

added_files = [

("sound", "sound"),
("img", "img")

]

Then, change the line of datas=[], to datas=added_files,然后,将datas=added_files, datas=[],行更改为datas=added_files,

For the details of the operations done on main.spec see here.有关在main.spec完成的操作的详细信息,请参见此处。

Run pyinstaller --onefile main.spec运行pyinstaller --onefile main.spec

And that is all, you can run main in project_folder/dist from anywhere, without having anything else in its folder.就是这样,您可以从任何地方在project_folder/dist运行main ,而在其文件夹中没有任何其他内容。 You can distribute only that main file.您只能分发该main文件。 It is now, a true standalone .现在,一个真正的独立.

Slight modification to the accepted answer.对接受的答案稍作修改。

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)

    return os.path.join(os.path.abspath("."), relative_path)

Using the excellent answer from Max and This post about adding extra data files like images or sound & my own research/testing, I've figured out what I believe is the easiest way to add such files.使用Max这篇关于添加额外数据文件(如图像或声音)和我自己的研究/测试的优秀答案,我找到了我认为添加此类文件的最简单方法。

If you would like to see a live example, my repository is here on GitHub.如果你想看到一个活生生的例子,我的仓库是这里GitHub上。

Note: this is for compiling using the --onefile or -F command with pyinstaller.注意:这是为了在--onefile使用--onefile-F命令进行编译。

My environment is as follows.我的环境如下。


Solving the problem in 2 steps分两步解决问题

To solve the issue we need to specifically tell Pyinstaller that we have extra files that need to be "bundled" with the application.为了解决这个问题,我们需要专门告诉 Pyinstaller 我们有额外的文件需要与应用程序“捆绑”在一起。

We also need to be using a 'relative' path , so the application can run properly when it's running as a Python Script or a Frozen EXE.我们还需要使用“相对”路径,以便应用程序在作为 Python 脚本或 Frozen EXE 运行时可以正常运行。

With that being said we need a function that allows us to have relative paths.话虽如此,我们需要一个允许我们拥有相对路径的函数。 Using the function that Max Posted we can easily solve the relative pathing.使用Max Posted的函数,我们可以轻松解决相对路径问题。

def img_resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

We would use the above function like this so the application icon shows up when the app is running as either a Script OR Frozen EXE.我们会像这样使用上面的函数,这样当应用程序作为脚本或 Frozen EXE 运行时,应用程序图标就会显示出来。

icon_path = img_resource_path("app/img/app_icon.ico")
root.wm_iconbitmap(icon_path)

The next step is that we need to instruct Pyinstaller on where to find the extra files when it's compiling so that when the application is run, they get created in the temp directory.下一步是我们需要指示 Pyinstaller 在编译时在哪里找到额外的文件,以便当应用程序运行时,它们会在临时目录中创建。

We can solve this issue two ways as shown in the documentation , but I personally prefer managing my own .spec file so that's how we're going to do it.我们可以通过两种方式解决这个问题,如文档中所示,但我个人更喜欢管理我自己的 .spec 文件,这就是我们要做的。

First, you must already have a .spec file.首先,您必须已经有一个 .spec 文件。 In my case, I was able to create what I needed by running pyinstaller with extra args, you can find extra argshere .就我而言,我能够通过运行带有额外参数的pyinstaller来创建我需要的pyinstaller ,您可以在此处找到额外的参数。 Because of this, my spec file may look a little different than yours but I'm posting all of it for reference after I explain the important bits.因此,我的规范文件可能看起来与您的略有不同,但在我解释了重要部分后,我将所有文件都发布以供参考。

added_files is essentially a List containing Tuple's, in my case I'm only wanting to add a SINGLE image, but you can add multiple ico's, png's or jpg's using ('app/img/*.ico', 'app/img') You may also create another tuple like so added_files = [ (), (), ()] to have multiple imports added_files本质上是一个包含元组的列表,在我的情况下,我只想添加单个图像,但您可以使用('app/img/*.ico', 'app/img')添加多个 ico、png 或 jpg您也可以像这样创建另一个元组added_files = [ (), (), ()]以进行多个导入

The first part of the tuple defines what file or what type of file's you would like to add as well as where to find them.元组定义你想什么文件或者文件的类型如加在哪里可以找到他们的第一部分。 Think of this as CTRL+C把它想象成 CTRL+C

The second part of the tuple tells Pyinstaller, to make the path 'app/img/' and place the files in that directory RELATIVE to whatever temp directory gets created when you run the .exe.元组的第二部分告诉 Pyinstaller,将路径设为“app/img/”,并将该目录中的文件与运行 .exe 时创建的任何临时目录相对应。 Think of this as CTRL+V把它想象成 CTRL+V

Under a = Analysis([main... , I've set datas=added_files , originally it used to be datas=[] but we want out the list of imports to be, well, imported so we pass in our custom imports.a = Analysis([main... , 我已经设置了datas=added_files ,最初它曾经是datas=added_files datas=[]但我们希望导入列表被导入,所以我们传入我们的自定义导入。

You don't need to do this unless you want a specific icon for the EXE, at the bottom of the spec file I'm telling Pyinstaller to set my application icon for the exe with the option icon='app\\\\img\\\\app_icon.ico' .你不需要这样做,除非你想要一个特定的 EXE 图标,在规范文件的底部,我告诉 Pyinstaller 使用选项icon='app\\\\img\\\\app_icon.ico'为 exe 设置我的应用程序图标icon='app\\\\img\\\\app_icon.ico'

added_files = [
    ('app/img/app_icon.ico','app/img/')
]
a = Analysis(['main.py'],
             pathex=['D:\\Github Repos\\Processes-Killer\\Process Killer'],
             binaries=[],
             datas=added_files,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='Process Killer',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True , uac_admin=True, icon='app\\img\\app_icon.ico')

Compiling to EXE编译成EXE

I'm very lazy;我很懒; I don't like typing things more than I have to.我不喜欢多打字。 I've created a .bat file that I can just click.我已经创建了一个 .bat 文件,我可以点击它。 You don't have to do this, this code will run in a command prompt shell just fine without it.您不必这样做,如果没有它,此代码将在命令提示符 shell 中运行。

Since the .spec file contains all of our compiling settings & args (aka options) we just have to give that .spec file to Pyinstaller.由于 .spec 文件包含我们所有的编译设置和参数(又名选项),我们只需将该 .spec 文件提供给 Pyinstaller。

pyinstaller.exe "Process Killer.spec"

The most common complaint/question I've seen wrt PyInstaller is "my code can't find a data file which I definitely included in the bundle, where is it?", and it isn't easy to see what/where your code is searching because the extracted code is in a temp location and is removed when it exits.我在 PyInstaller 上看到的最常见的抱怨/问题是“我的代码找不到我肯定包含在包中的数据文件,它在哪里?”,并且不容易看到代码的内容/位置正在搜索,因为提取的代码位于临时位置并在退出时被删除。 Add this bit of code to see what's included in your onefile and where it is, using @Jonathon Reinhart's resource_path()使用@Jonathon Reinhart 的resource_path()添加这段代码以查看您的 onefile 中包含的内容及其位置

for root, dirs, files in os.walk(resource_path("")):
    print(root)
    for file in files:
        print( "  ",file)

Another solution is to make a runtime hook, which will copy(or move) your data (files/folders) to the directory at which the executable is stored.另一种解决方案是制作一个运行时挂钩,它将复制(或移动)您的数据(文件/文件夹)到存储可执行文件的目录。 The hook is a simple python file that can almost do anything, just before the execution of your app. hook 是一个简单的 python 文件,几乎可以做任何事情,就在你的应用程序执行之前。 In order to set it, you should use the --runtime-hook=my_hook.py option of pyinstaller.为了设置它,您应该使用--runtime-hook=my_hook.py选项。 So, in case your data is an images folder, you should run the command:因此,如果您的数据是一个图像文件夹,您应该运行以下命令:

pyinstaller.py --onefile -F --add-data=images;images --runtime-hook=cp_images_hook.py main.py

The cp_images_hook.py could be something like this: cp_images_hook.py 可能是这样的:

import sys
import os
import shutil

path = getattr(sys, '_MEIPASS', os.getcwd())

full_path = path+"\\images"
try:
    shutil.move(full_path, ".\\images")
except:
    print("Cannot create 'images' folder. Already exists.")

Before every execution the images folder is moved to the current directory (from the _MEIPASS folder), so the executable will always have access to it.在每次执行之前,图像文件夹被移动到当前目录(来自 _MEIPASS 文件夹),因此可执行文件将始终可以访问它。 In that way there is no need to modify your project's code.这样就无需修改项目的代码。

Second Solution第二种解决方案

You can take advantage of the runtime-hook mechanism and change the current directory, which is not a good practice according to some developers, but it works fine.您可以利用运行时挂钩机制并更改当前目录,根据某些开发人员的说法,这不是一个好的做法,但它工作正常。

The hook code can be found below:钩子代码可以在下面找到:

import sys
import os

path = getattr(sys, '_MEIPASS', os.getcwd())   
os.chdir(path)

I found the existing answers confusing, and took a long time to work out where the problem is.我发现现有的答案令人困惑,并花了很长时间才找出问题所在。 Here's a compilation of everything I found.这是我找到的所有内容的汇编。

When I run my app, I get an error Failed to execute script foo (if foo.py is the main file).当我运行我的应用程序时,出现错误Failed to execute script foo (如果foo.py是主文件)。 To troubleshoot this, don't run PyInstaller with --noconsole (or edit main.spec to change console=False => console=True ).要解决此问题,请不要使用--noconsole运行 PyInstaller(或编辑main.spec以更改console=False => console=True )。 With this, run the executable from a command-line, and you'll see the failure.有了这个,从命令行运行可执行文件,你会看到失败。

The first thing to check is that it's packaging up your extra files correctly.首先要检查的是它是否正确打包了您的额外文件。 You should add tuples like ('x', 'x') if you want the folder x to be included.如果您希望包含文件夹x ,您应该添加像('x', 'x')这样的元组。

After it crashes, don't click OK.崩溃后,不要单击“确定”。 If you're on Windows, you can use Search Everything .如果您使用的是 Windows,则可以使用Search Everything Look for one of your files (eg. sword.png ).查找您的文件之一(例如sword.png )。 You should find the temporary path where it unpacked the files (eg. C:\\Users\\ashes999\\AppData\\Local\\Temp\\_MEI157682\\images\\sword.png ).您应该找到解压缩文件的临时路径(例如C:\\Users\\ashes999\\AppData\\Local\\Temp\\_MEI157682\\images\\sword.png )。 You can browse this directory and make sure it included everything.您可以浏览此目录并确保它包含所有内容。 If you can't find it this way, look for something like main.exe.manifest (Windows) or python35.dll (if you're using Python 3.5).如果您无法通过这种方式找到它,请查找类似main.exe.manifest (Windows) 或python35.dll (如果您使用的是 Python 3.5)的内容。

If the installer includes everything, the next likely problem is file I/O: your Python code is looking in the executable's directory, instead of the temp directory, for files.如果安装程序包含所有内容,下一个可能的问题是文件 I/O:您的 Python 代码正在可执行文件的目录中查找文件,而不是在临时目录中查找文件。

To fix that, any of the answers on this question work.为了解决这个问题,这个问题的任何答案都有效。 Personally, I found a mixture of them all to work: change directory conditionally first thing in your main entry-point file, and everything else works as-is:就我个人而言,我发现它们都可以工作:在主入口点文件中首先有条件地更改目录,其他一切都按原样运行:

if hasattr(sys, '_MEIPASS'): os.chdir(sys._MEIPASS)

If you are still trying to put files relative to your executable instead of in the temp directory, you need to copy it yourself.如果您仍然试图将文件相对于您的可执行文件而不是放在临时目录中,您需要自己复制它。 This is how I ended up getting it done.这就是我最终完成它的方式。

https://stackoverflow.com/a/59415662/999943 https://stackoverflow.com/a/59415662/999943

You add a step in the spec file that does a filesystem copy to the DISTPATH variable.您在规范文件中添加一个步骤,将文件系统复制到 DISTPATH 变量。

Hope that helps.希望有帮助。

i use this based on max solution我使用这个基于最大解决方案

def getPath(filename):
    import os
    import sys
    from os import chdir
    from os.path import join
    from os.path import dirname
    from os import environ
    
    if hasattr(sys, '_MEIPASS'):
        # PyInstaller >= 1.6
        chdir(sys._MEIPASS)
        filename = join(sys._MEIPASS, filename)
    elif '_MEIPASS2' in environ:
        # PyInstaller < 1.6 (tested on 1.5 only)
        chdir(environ['_MEIPASS2'])
        filename = join(environ['_MEIPASS2'], filename)
    else:
        chdir(dirname(sys.argv[0]))
        filename = join(dirname(sys.argv[0]), filename)
        
    return filename

For those of whom are still looking for a more recent answer, here you go:对于那些仍在寻找更新答案的人,请看这里:

In the documentation , there's a section on accessing added data files .文档中,有一节是关于访问添加的数据文件的
Here is the short and sweet of it.这是它的简短和甜蜜。


You'll want to import pkgutil and locate which folder you added the datafile to;您需要import pkgutil并找到将数据文件添加到的文件夹; ie the second string in the tuple which was added to the spec file:即添加到规范文件的元组中的第二个字符串:

datas = [("path/to/mypackage/data_file.txt", "path/to/mypackage")]

Knowing where you added the data file can then be used for reading it in as binary data, and decoding it as you wish.知道您添加数据文件的位置然后可用于将其作为二进制数据读入,并根据需要对其进行解码。 Take this example:拿这个例子:

File structure:文件结构:

mypackage
      __init__.py  # This is a MUST in order for the package to be registered
      data_file.txt  # The data file you've added

data_file.txt数据文件.txt

Hello world!

main.py主文件

import pkgutil

file = pkgutil.get_data("mypackage", "data_file.txt")
contents = file.decode("utf-8")
print(contents)  # Hello world!

References:参考:

Чтобы скомпилировать при помощи auto-py-to-exe: Указываем расположение скрипта, выбираем --onefile (одним файлом, --windowed (скрыть консоль), указываем путь к значку (иконке) img.ico (у вас имя файла вашей иконки, добавляем дополнительный файл img.icon (в вашем случае файл вашей иконки), вводим в поле названия файла то имя как ваш файл будет называться после того как скомпилируется. У меня в примере он file_name. Чтобыскомпилироватьприпомощи自动PY到EXE:Указываемрасположениескрипта,выбираем--onefile(однимфайлом,--windowed(скрытьконсоль),указываемпутькзначку(иконке)img.ico(увасимяфайлавашейиконки, добавляемдополнительныйфайлimg.icon(ввашемслучаефайлвашейиконки),вводимвполеназванияфайлатоимякаквашфайлбудетназыватьсяпослетогокакскомпилируется。УменявпримереонFILE_NAME。

В самом скрипте прописываем путь "dist\\file_name\\img.ico", где file_name это имя вашего будущего exe файла, img.ico имя файла вашей иконки. В самом скрипте прописываем путь "dist\\file_name\\img.ico", где file_name это имя вашего будущего exe файла, img.ico имя файла вашей иконки。

icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("dist\\file_name\\img.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap("dist\\file_name\\img.ico"), QtGui.QIcon.Normal, QtGui.QIcon.On) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("dist\\file_name\\img.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap("dist\\file_name \\img.ico"), QtGui.QIcon.Normal, QtGui.QIcon.On)

Итог - получаем файл exe с отображение иконок не зависимо где файл открывается... Итог - получаем файл exe с отображение иконок не зависимо где файл открывается...

"

FINALLY !最后 ! based on solution from Luca基于Luca的解决方案

I was able to finaly execute files inside included directory in --onefile pyinstaller.我最终能够在 --onefile pyinstaller 的包含目录中执行文件。

Just use the method he posted and you can even enter a whole directory name to files and it still works.只需使用他发布的方法,您甚至可以将整个目录名称输入文件,它仍然有效。

Second thing you will need is actually add the directory/files you want inside pyinstaller.您需要做的第二件事实际上是在 pyinstaller 中添加您想要的目录/文件。 Just use args like:只需使用如下参数:

--add-data "yourDir/And/OrFile;yourDir"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM