使用Cython编译主Python程序
我有一个用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命令行的例子吗?谢谢。
5 个回答
我不知道这是否有帮助,但Nudzo说得对。你可以用 cython --embed -o main.o main.py
这个命令来获取结果,然后我尝试用 cl/EHsc 来编译这个结果。
看看这个问题的回答:Cython能编译成EXE吗?,这里的回答和其他地方的说法不一样,他们说是可以把Cython编译成可执行文件的。
在嵌入Cython的链接里,似乎是个不错的起点,但这并不是Cython的主要目的,所以我不太确定这个过程会有多简单。
与亚当·马坦和其他人所说的相反,你确实可以使用Cython从一个纯Python(.py)文件创建一个单独的可执行二进制文件。
是的,Cython的确是为了简化为CPython Python运行环境编写C/C++扩展模块而设计的。
但是,正如nudzo在这个评论中提到的,你可以在命令行中使用--embed
这个选项。
这里有一个非常简单的例子。我是在一台运行Debian Sid的工作站上,使用python3和cython3进行操作。
确保你事先安装了python-dev或python3-dev包。
1) 创建一个非常简单的Python程序,命名为hello.py
$ cat hello.py
print("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的文件...
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 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) 运行hello...
$ ./hello
Hello World!
如你所见,使用这种方法,你基本上可以用Cython将你的纯Python应用程序转换为可执行的编译对象代码。
我正在使用这种方法来处理更复杂的应用程序,比如一个完整的Python/PySide/Qt应用。
对于不同版本的Python,你可以根据需要调整gcc的-I
和-l
选项。
然后你可以将这个可执行文件打包成一个发行版文件(.deb等),而不需要打包Python/PySide/Qt的文件——这样做的好处是,即使在同一发行版上更新到相同版本的Python等,你的应用程序仍然可以运行。