与 Adam Matan 和其他人所断言的相反,您实际上可以使用 Cython 从纯 Python (.py) 文件创建单个可执行二进制文件。
是的,Cython 旨在按规定使用 - 作为一种简化为 CPython python 运行时编写 C/C++ 扩展模块的方式。
但是,正如 nudzo 在此 comment 中提到的那样,您可以在命令行提示符处使用 --embed 开关。
这是一个非常简单的例子。我正在使用 python3 和 cython3 从 Debian Sid 工作站执行此操作..
确保您事先安装了 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 ...
的文件
$文件你好
你好: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) 运行 hello...
$ ./你好
世界你好!
如您所见,使用这种方法,您基本上可以使用 Cython 将纯 Python 应用程序转换为可执行的编译目标代码。
我将这种方法用于更复杂的应用程序 - 例如,成熟的 Python/PySide/Qt 应用程序。
对于不同版本的 Python,您可以定制 gcc -I 和 -l 开关以适合。
然后您可以将可执行文件打包为分发(.deb 等)文件,而无需打包 Python/PySide/Qt 文件 - 优点是即使在分发更新后您的应用程序仍应能够运行到该发行版上相同版本的 Python 等。