使用Cython编译主要的Python程序


81

我有一个Python2.6程序,可以使用Cython加载编译为.so文件的Python模块。我使用Cython将.py模块编译为.so文件,并且一切正常。

这是我与Cython一起使用的setup.py文件:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("ldap", ["ldap.pyx"]),
    Extension("checker", ["checker.pyx"]),
    Extension("finder", ["finder.pyx"]),
    Extension("utils", ["utils.pyx"]),
]

setup(
  name = 'bchecker',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

因此,我知道我可以使用Cython编译Python模块(我想Cython会从我的Python文件创建“ C”文件,然后对其进行编译),但是我可以将我的主Python程序编译为可以在Linux平台上执行的程序吗?如果是这样,将不胜感激Cython命令行示例。谢谢。


4
这些答案有用吗?你有工作吗?如果是这样,请接受答案
Mike Pennington

3
我怀疑这是否会被标记-在问题的编辑日期后的第二天才看到该用户。
破碎的人

Answers:


152

与Adam Matan和其他人断言的相反,实际上您可以使用Cython从纯Python(.py)文件创建一个可执行二进制文件。

是的,Cython旨在按规定使用-一种简化为CPython python运行时编写C / C ++扩展模块的方式。

但是,正如nudzo在此注释中所暗示的那样,您可以--embed在命令行提示符下使用该开关。

这是一个非常简单的示例。我正在使用python3和cython3在Debian Sid工作站上执行此操作。

确保事先安装了python-devpython3-dev软件包。

1)创建一个非常简单的Python程序hello.py

$猫hello.py

打印(“ Hello World!”)

2)使用Cython将您的python程序编译为C ...

cython3 --embed -o hello.c hello.py

3)使用GCC将hello.c编译成名为hello的可执行文件...

gcc -Os -I /usr/include/python3.3m -o hello hello.c -lpython3.3m -lpthread -lm -lutil -ldl

4)您最终得到一个名为hello的文件...

$文件你好

你好:ELF 64位LSB可执行文件,x86-64,版本1(SYSV),动态链接(使用共享库),用于GNU / Linux 2.6.32,BuildID [sha1] = 006f45195a26f1949c6ed051df9cbd4433e1ac23,未剥离

$ ldd hello
linux-vdso.so.1 (0x00007fff273fe000)
libpython3.3m.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython3.3m.so.1.0 (0x00007fc61dc2c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc61da0f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc61d70b000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc61d508000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc61d304000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc61cf5a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc61cd52000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fc61cb28000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc61c90f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc61e280000)

在这种情况下,可执行文件将动态链接到我的Debian系统上的Python 3.3。

5)运行你好...

$ ./您好

你好,世界!

如您所见,使用这种方法,您基本上可以使用Cython将纯Python应用程序转换为可执行的,已编译的目标代码。

我将这种方法用于非常复杂的应用程序,例如,功能完善的Python / PySide / Qt应用程序。

对于不同版本的Python,您可以定制gcc-I-l开关以适合。

然后,您可以将可执行文件打包为分发文件(.deb等),而不必打包Python / PySide / Qt文件-优点是即使将分发文件更新为相同版本,您的应用程序仍应能够运行该发行版上的Python版本等。


嵌入方法可用于生成动态库而不是可执行文件吗?
denfromufa 2014年

5
它不会将模块编译为可执行文件。是否有可能提供一个可移植的可执行文件,即已将以源代码导入的每个模块都编译为该可执行文件。@BrokenMan
Devesh Saini

1
@DeveshSaini我没有花时间试图找出答案。我设法使一个成熟的python + Pyside应用程序如上所述进行编译的唯一方法是以常规方式开发该程序-许多include <mymodule>语句+使用解释器进行测试。然后,当一切准备就绪时,我手动粘贴所有包含的代码,并注释掉它们替换的relevent include语句。是的,这是不希望的,但是就像我最初说的那样,我没有花时间去看我如何仅编译主例程并将所包含的模块链接在一起。
破碎的人

3
libpython的静态链接呢?
詹姆斯·米尔斯

4
对于python 2.7cython --embed -o /tmp/a.c a.pygcc -Os -I /usr/include/python2.7 -o /tmp/a/tmp/a.c -lpython2.7 -lpthread -lm -lutil -ldl
dsaydon


4

我不知道这是否会有所帮助,但Nudzo是正确的。您可以使用它,cython --embed -o main.o main.py然后尝试用cl / EHsc编译结果


-21

您不能,Cython不能编译Python也不可以将其转换为可执行文件。

要生成一个.exe文件,请使用py2exe

要生成适用于Mac或Linux的软件包,请使用常规打包系统过程,因为Unix env中的脚本语言程序没有特殊要求。


2
好吧,它使我可以将.py文件转换成.so文件。请参阅上面使用的脚本。.so文件不包含可执行代码?
mozza

这不是目的。Cython用于编译C / C ++ Python扩展,而不是将Python脚本转换为可执行文件。
e-satis

9
误传。有cython --embed能产生可执行与把Python。
nudzo 2014年

除非您静态链接它,否则生成的可执行文件仍然依赖于libpython。此外,它不会在您所有文件中生成一个可执行文件,而是在您的入口点中生成一个可执行文件。
e-satis 2014年

2
@ e-satis是的,可执行文件将动态链接到当时针对其编译的libpython版本。怎么了 如果它是针对Linux的,并且您打算分发您的应用程序,则只需将其打包为您要定位的任何Linux分发格式即可,就像其他二进制软件包一样。例如myapp_1_wheezy_amd64.deb将是您与该发行版的python2或python3链接的已编译python应用程序。对于Windows,只需提供所需的python。同样,我在这里看不到问题或异议。
破碎的人
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.