有人成功地用Pyinstaller将数据文件打包成一个文件吗?

9

我一直在Stack Overflow和其他网站上搜索如何将数据文件添加到我的Python应用程序中:

import Tkinter

class simpleapp_tk(Tkinter.Tk):
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        self.grid()

--- Everything Fine Here ---

        self.B = Tkinter.Button(self, text = 'Create Document', command = self.OnButtonClick)
        self.B.grid(column = 0, row = 6)


    def OnButtonClick(self):
        createDoc()

if __name__ == "__main__":
    app = simpleapp_tk(None)
    app.title('Receipt Form')
    app.iconbitmap(os.getcwd() + '/M.ico')
    app.mainloop()

我尝试使用.spec文件,但没有成功。

Onedir正常运行,但是当我尝试编译成单个可执行文件时,它会报错,说文件'M.ico'未定义。

如果有人能够将数据文件与PyInstaller打包成单个文件,请帮忙。谢谢。

我使用的是安装有Python 2.7和PyInstaller 3.2的Windows 10计算机。


我认为你的问题在于 pyinstaller 使用临时文件夹来提取文件。你需要在代码中为冻结的应用程序指定,就像这里所做的那样 here - Repiklis
@Repiklis 好的,但我该怎么使用呢?是这样做吗 app.iconbitmap(resource_path('/M.ico')) - Michael Zheng
这与非常相似。你需要将你的图标包含在spec文件的resources中,并在代码底部添加答案中的两行代码(在设置图标之前)。如果你仍然有问题,请告诉我。 - Repiklis
@Repiklis 我按照你说的做了:我在我的spec文件末尾添加了resources=['M.ico']),并在我的实际Python文件中添加了if hasattr(sys, '_MEIPASS'): os.chdir(sys._MEIPASS),但我仍然收到错误消息:_tkinter.TclError: bitmap "C:\Users\micha\AppData\Local\Temp\_MEI69~1/M.ico" not defined - Michael Zheng
你现在用在“M.ico”前面的斜杠是错误的。这种情况下应该写成“\M.ico”。更好的做法是使用os.sep来获取系统路径分隔符。 - Repiklis
1个回答

7

您必须在pyinstaller .spec文件中或通过命令行选项指定要添加的每个数据文件(.spec更容易一些)。以下是我的.spec文件,其中包含“数据”部分:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['pubdata.py'],
             pathex=['.', '/interface','/recommender'],
             binaries=None,
             datas=[('WordNet/*.txt','WordNet'),
             ('WordNet/*.json','WordNet'),
             ('WordNet/pdf_parsing/*.json','pdf_parsing'),
             ('WordNet/pdf_parsing/*.xml','pdf_parsing'),
             ('images/*.png','images'),
             ('database/all_meta/Flybase/*.txt','all_meta'),
             ('database/all_meta/Uniprot/*.txt','all_meta'),
             ('database/json_files/*.json','json_files'),
             ('Data.db','.')],

             hiddenimports=['interface','recommender'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='GUI',
          debug=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='GUI')
app = BUNDLE(coll,
             name='App.app',
             icon=None)

在此之后,如果您尝试在代码中访问您在 .spec 文件中指定的任何数据文件,您必须使用 Pyinstaller 的 _MEIPASS 文件夹来引用您的文件。以下是我如何使用名为 Data.db 的文件:

import sys
import os.path

        if hasattr(sys, "_MEIPASS"):
            datadir = os.path.join(sys._MEIPASS, 'Data.db')
        else:
            datadir = 'Data.db'

        conn = lite.connect(datadir)

这种方法替换了原本独立存在的语句:
conn = lite.connect("Data.db")

这个链接在我遇到同样的问题时帮了我很多: https://irwinkwan.com/2013/04/29/python-executables-pyinstaller-and-a-48-hour-game-design-compo/ 希望对你有所帮助!

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