简体   繁体   English

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

[英]Building Cython-compiled python code with PyInstaller

I am trying to build a Python multi-file code with PyInstaller .我正在尝试使用PyInstaller构建 Python 多文件代码。 For that I have compiled the code with Cython , and am using .so files generated in place of .py files.为此,我使用Cython编译了代码,并使用生成的.so文件代替.py文件。

Assuming the 1st file is main.py and the imported ones are file_a.py and file_b.py , I get file_a.so and file_b.so after Cython compilation.假设第一个文件是main.py和进口的有file_a.pyfile_b.py ,我得到file_a.sofile_b.so用Cython编译后。

When I put main.py , file_a.so and file_b.so in a folder and run it by "python main.py" , it works.当我将main.pyfile_a.sofile_b.so放在一个文件夹中并通过"python main.py"运行它时,它可以工作。

But when I build it with PyInstaller and try to run the executable generated, it throws errors for imports done in file_a and file_b .但是当我使用PyInstaller构建它并尝试运行生成的可执行文件时,它会为在file_afile_b完成的导入引发错误。

How can this be fixed?如何解决这个问题? One solution is to import all standard modules in main.py and this works.一种解决方案是在main.py导入所有标准模块,这很有效。 But if I do not wish to change my code, what can be the solution?但是如果我不想改变我的代码,有什么解决办法呢?

So I got this to work for you.所以我让这个为你工作。

Please have a look at Bundling Cython extensions with Pyinstaller请查看使用 Pyinstaller 捆绑 Cython 扩展

Quick Start:快速开始:

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

This produces a static binary:这会生成一个静态二进制文件:

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

And produces the output:并产生输出:

$ ./dist/hello 
Hello World!
FooBar

Basically this came down to producing a simple setup.py that builds the extensions file_a.so and file_b.so and then uses pyinstaller to bundle the application the extensions into a single executeble.基本上,这归结为生成一个简单的setup.py ,它构建扩展file_a.sofile_b.so ,然后使用pyinstaller将应用程序的扩展捆绑到单个可执行文件中。

Example setup.py :示例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")
)

Building the extensions:构建扩展:

$ python setup.py develop

Bundling the application:捆绑应用程序:

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

Just in case someone's looking for a quick fix.以防万一有人正在寻找快速解决方案。

I ran into the same situation and found a quick/dirty way to do the job.我遇到了同样的情况,并找到了一种快速/肮脏的方式来完成这项工作。 The issue is that pyinstaller is not adding the necessary libraries in the .exe file that are needed to run your program.问题是 pyinstaller 没有在 .exe 文件中添加运行程序所需的必要库。

All you need to do is import all the libraries (and the .so files) needed into your main.py file (the file which calls file_a.py and file_b.py).您需要做的就是将所需的所有库(和 .so 文件)导入 main.py 文件(调用 file_a.py 和 file_b.py 的文件)。 For example, assume that file_a.py uses opencv library (cv2) and file_b.py uses matplotlib library.例如,假设 file_a.py 使用 opencv 库(cv2),file_b.py 使用 matplotlib 库。 Now in your main.py file you need to import cv2 and matplotlib as well.现在在您的 main.py 文件中,您还需要导入 cv2 和 matplotlib。 Basically, whatever you import in file_a.py and file_b.py, you have to import that in main.py as well.基本上,无论你在 file_a.py 和 file_b.py 中导入什么,你也必须在 main.py 中导入它。 This tells pyinstaller that the program needed these libraries and it includes those libraries in the exe file.这告诉 pyinstaller 程序需要这些库,并且它在 exe 文件中包含这些库。

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

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