使用PyInstaller构建Cython编译的python代码

时间:2014-07-02 07:59:47

标签: python cython pyinstaller

我正在尝试使用PyInstaller构建Python多文件代码。为此,我使用Cython编译了代码,并使用生成的.so文件代替.py个文件。

假设第一个文件是main.py且导入的文件是file_a.pyfile_b.py,我在Cython编译后得到file_a.sofile_b.so

当我将main.pyfile_a.sofile_b.so放入文件夹并按"python main.py"运行时,它可以正常工作。

但是当我使用PyInstaller构建它并尝试运行生成的可执行文件时,它会导致file_afile_b中完成的导入错误。

如何解决这个问题?一种解决方案是导入main.py中的所有标准模块,这是有效的。但如果我不想改变我的代码,可以解决什么问题呢?

2 个答案:

答案 0 :(得分:15)

所以我让这个为你工作。

请查看Bundling Cython extensions with Pyinstaller

快速入门:

git clone https://github.com/prologic/pyinstaller-cython-bundling.git
cd pyinstaller-cython-bundling
./dist/build.sh

这会生成一个静态二进制文件:

$ du -h dist/hello
4.2M    dist/hello
$ ldd dist/hello
    not a dynamic executable

并产生输出:

$ ./dist/hello 
Hello World!
FooBar

基本上,这产生了一个简单的setup.py,用于构建扩展file_a.sofile_b.so,然后使用pyinstaller将扩展应用程序捆绑到单个executebla中。

示例setup.py

from glob import glob
from setuptools import setup
from Cython.Build import cythonize


setup(
    name="test",
    scripts=glob("bin/*"),
    ext_modules=cythonize("lib/*.pyx")
)

构建扩展程序:

$ python setup.py develop

捆绑应用程序:

$ pyinstaller -r file_a.so,dll,file_a.so -r file_b.so,dll,file_b.so -F ./bin/hello

答案 1 :(得分:0)

以防万一有人在寻找快速解决方案。

我遇到了同样的情况,发现一种快速/肮脏的方式来完成这项工作。问题是pyinstaller没有在.exe文件中添加运行程序所需的必需库。

您需要做的就是将所有需要的库(和.so文件)导入到main.py文件(调用file_a.py和file_b.py的文件)中。例如,假设file_a.py使用opencv库(cv2),而file_b.py使用matplotlib库。现在,在main.py文件中,您还需要导入cv2和matplotlib。基本上,无论您在file_a.py和file_b.py中导入什么内容,都必须在main.py中也导入它。这告诉pyinstaller该程序需要这些库,并且在exe文件中包括这些库。