适用于kivy的PyInstaller软件包

时间:2014-06-26 09:13:55

标签: python packaging kivy pyinstaller

我最近尝试使用kivy从我的PyInstaller应用程序中构建一个包。我的目标是创建一个可以在我的Linux(Ubuntu 14.04 64位)上执行的包,并将其复制到其他Linux系统。

我试着整晚正确地执行PyInstaller,尝试了各种各样的东西,最终成功地为我自己的系统创建了一个包。首先,我想知道我在功能上打包我的应用程序到底做了什么。

我的main.spec文件如下所示:

# Part A
from kivy.tools.packaging.pyinstaller_hooks import install_hooks
install_hooks(globals())
# -*- mode: python -*-

# Part B
from PyInstaller.hooks.hookutils import exec_statement
hiddenimports = ['pysqlite2', 'MySQLdb', 'psycopg2']
databases = exec_statement("import sqlalchemy.databases;
print sqlalchemy.databases.__all__")
databases = eval(databases.strip())
for n in databases:
    hiddenimports.append("sqlalchemy.databases." + n)
version = exec_statement('import sqlalchemy; print sqlalchemy.__version__')
is_alch06 = version >= '0.6'

if is_alch06:
    dialects = exec_statement("import sqlalchemy.dialects; print sqlalchemy.dialects.__all__")
    dialects = eval(dialects.strip())

    for n in databases:
        hiddenimports.append("sqlalchemy.dialects." + n)

block_cipher = None

# Part C
a = Analysis(['main.py'],
         pathex=['/home/grafgustav/Python/ICCHP/accessmail/src','/'],
         hiddenimports=[],
         cipher=block_cipher)
pyz = PYZ(a.pure,
         cipher=block_cipher)
exe = EXE(pyz,
      a.scripts,
      exclude_binaries=True,
      name='main',
      debug=False,
      strip=None,
      upx=True,
      console=True )


coll = COLLECT(exe, Tree("/home/grafgustav/Python/ICCHP/accessmail"),
           a.binaries, #...,
           a.zipfiles,
           a.datas,
           strip=None,
           upx=True,
           name='main',
           )

虽然我理解为什么B部分主要是多余的(我只是从互联网的某个地方复制了那个部分)而且A部分得到了kivy的一些完成的钩子,我不太明白为什么这不包装整个应用程序我喜欢它。

据我所知,钩子用于包含不直接导入的库,而是隐式或在运行时。就像隐藏进口一样。

主要问题是我生成的包中缺少的部分。有一个文件夹" GUI"在我的整个src目录中,其中包含特定于kivy的* .kv文件。包含此GUI文件夹的src文件夹包含在结果包中,当我尝试启动程序时,* .kv文件仍然缺失。所以我试图将GUI文件夹复制到我打包的#34; main"位于,* .kv文件不再丢失。为什么PyInstaller会复制整个src文件夹但却无法正确检测GUI文件夹? 我得到的下一个错误与sqlalchemy有关。由于我已经添加了一些sqlalchemy钩子,我认为打包的应用程序无法找到我用来存储数据的data.db。这个位于我正在打包的main.py上方的一个文件夹中。它包含在结果中,但不在正确的位置。如果我将data.db复制到我生成的main上面的一个文件夹,则此错误也会得到解决。 我的最后一个错误,它阻止了程序包的工作,这是由一些kivy特定的东西引起的。错误消息说,文件[包目录] /kivy/data/style.kv丢失了。实际上甚至没有文件夹" kivy"。我在kivy源代码中搜索了这个文件,将其复制到了正确的目录,现在它可以在我的系统上运行。 现在我想知道为什么我必须手动将所有这些文件复制到我的结果目录中。如何告诉PyInstaller事先包含这些文件? 它适用于我的系统(我打包它),但在我的第二个系统(Ubuntu 12.04LTS 64位,关于错误的OpenGL版本的一些错误)上,在测试系统上(fedora,根本没有错误,只有{{ 1}})或在我大学的计算机上(Debian 3.2.57 64位,`。/ main:/lib/x86_64-linux-gnu/libc.so.6:版本GLIBC_2.14未找到(需要/ libz.so.1)。

我的朋友在他的Windows系统上使用过PyInstaller,也有一些问题(他必须手动将上面提到的文件/文件夹添加到包中)但最终它在Win7和Win8上工作同样没问题。 / p>

如何在我自己的系统上使用PyInstaller为其他Linux系统制作可执行文件?我甚至对main could not be executed文件做了什么?或者是否有更好的方法为python应用程序创建可执行文件?

1 个答案:

答案 0 :(得分:0)

我不是专家,但我会分享我所知道的

将文件夹添加到生成的包中:

  

现在我想知道,为什么我必须将所有这些文件复制到我的结果中   目录手动。如何告诉PyInstaller包含这些文件   预先?

在COLLECT部分​​定义二进制文件时,调用Tree(),它应该使用prefix参数,因此pyInstaller知道将文件夹accessmail放在哪里与'src'相关文件夹:

Tree("/home/grafgustav/Python/ICCHP/accessmail", prefix='..')

但我从来没有尝试用'..'作为前缀,必须测试它。

将文件添加到生成的包中:

  

打包的应用程序无法使用   找到data.db我用来存储我的数据。这个位于一个   我正在打包的main.py上面的文件夹。它包含在结果中,   但不是在正确的位置。

要将任意文件添加到二进制文件中,您只需要创建一个包含3个值的元组:

a.binaries += [(file_address, file_result_address, 'DATA')]

file_result_address是文件保留在生成包中的位置。

要添加更多文件,只需在“[]”:

之间添加更多元组
[(addr,addr,type), (addr,addr,type), ...]

让它适用于多个系统:

我可以给出的第一个提示是尝试在32位系统上进行编译,因此它可以在32位和64位系统上运行。

正如this post第3部分所建议的那样,您可能会尝试从包中删除系统库并将它们作为依赖项添加,因此它将使用本机库。上面的链接提供了一个python函数来在.spec内完成这项工作。

制作单个二进制文件而不是包含所有依赖项的文件夹:

  

如何在我自己的系统上使用PyInstaller为其他Linux系统制作可执行文件?

如果您希望将单个二进制文件作为输出而不是具有所有依赖项的文件夹,则需要使用--onefile选项创建.spec文件。您可以在此之后将相关部分复制到您的代码中:

pyinstaller --onefile myscript.py

您可以获得有关官方pyinstaller documentation的更多信息,这对我帮助很大。

我希望它有所帮助。