Biên dịch chương trình Python chính bằng Cython


81

Tôi có một chương trình Python2.6 có thể tải các mô-đun Python được biên dịch thành tệp .so bằng cách sử dụng Cython. Tôi đã sử dụng Cython để biên dịch các mô-đun .py thành tệp .so và mọi thứ đều hoạt động tốt.

Đây là tệp setup.py tôi sử dụng với Cython:

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
)

Vì vậy, tôi biết tôi có thể biên dịch các mô-đun Python bằng Cython (tôi đoán Cython tạo tệp 'C' từ các tệp Python của tôi và sau đó biên dịch chúng), nhưng tôi có thể biên dịch chương trình Python chính của mình thành thứ mà tôi có thể thực thi trên nền tảng Linux không? Nếu vậy, một ví dụ dòng lệnh Cython sẽ được đánh giá cao. Cảm ơn.


4
Có câu trả lời nào hữu ích không? Bạn đã nhận được điều này làm việc? Nếu vậy, hãy chấp nhận một câu trả lời
Mike Pennington

3
Tôi nghi ngờ điều này sẽ không bao giờ được đánh dấu - người dùng được nhìn thấy lần cuối một ngày sau ngày chỉnh sửa câu hỏi.
Broken Man

Câu trả lời:


152

Trái ngược với những gì Adam Matan và những người khác khẳng định, trên thực tế bạn có thể tạo một tệp nhị phân thực thi duy nhất bằng Cython, từ một tệp Python (.py) thuần túy.

Có, Cython nhằm mục đích được sử dụng như đã nêu - như một cách đơn giản hóa việc viết các mô-đun mở rộng C / C ++ cho thời gian chạy python CPython.

Tuy nhiên, như nudzo ám chỉ trong nhận xét này , bạn có thể sử dụng công --embedtắc tại dấu nhắc dòng lệnh.

Đây là một ví dụ cực kỳ đơn giản. Tôi đang thực hiện điều này từ một máy trạm Debian Sid, sử dụng python3 và cython3 ..

Hãy chắc chắn rằng bạn có cài đặt gói python-dev hoặc python3-dev trước đó.

1) Tạo một chương trình Python rất đơn giản có tên hello.py

$ cat hello.py

print ("Xin chào Thế giới!")

2) Sử dụng Cython để biên dịch chương trình python của bạn thành C ...

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

3) Sử dụng GCC để biên dịch hello.c thành một tệp thực thi được gọi là hello ...

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

4) Bạn kết thúc với một tệp có tên hello ...

$ file xin chào

xin chào: ELF 64-bit LSB thực thi, x86-64, phiên bản 1 (SYSV), được liên kết động (sử dụng các lib được chia sẻ), dành cho GNU / Linux 2.6.32, BuildID [sha1] = 006f45195a26f1949c6ed051df9cbd4433e1ac23, không bị tước

$ 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)

Trong trường hợp này, tệp thực thi được liên kết động với Python 3.3 trên hệ thống Debian của tôi.

5) chạy xin chào ...

$ ./hello

Chào thế giới!

Như bạn có thể thấy, sử dụng phương pháp này về cơ bản, bạn có thể sử dụng Cython để chuyển đổi các ứng dụng Python thuần túy của mình thành mã đối tượng được biên dịch, thực thi.

Tôi đang sử dụng phương pháp này cho các ứng dụng phức tạp hơn rất nhiều - ví dụ: ứng dụng Python / PySide / Qt hoàn chỉnh.

Đối với các phiên bản Python khác nhau, bạn điều chỉnh gcc -I-lcông tắc cho phù hợp.

Sau đó, bạn có thể đóng gói tệp thực thi dưới dạng tệp phân phối (.deb, v.v.), mà không cần phải đóng gói tệp Python / PySide / Qt - ưu điểm là ứng dụng của bạn vẫn có thể chạy ngay cả sau khi cập nhật phân phối lên cùng phiên bản Python, v.v. trên bản phân phối đó.


phương pháp nhúng này có thể được sử dụng để tạo một thư viện động thay vì thực thi không?
denfromufa

5
Nó không biên dịch (các) mô-đun thành tệp thực thi. Có thể có một tệp thực thi di động tức là mọi mô-đun đã được nhập trong mã nguồn sẽ được biên dịch thành tệp thực thi đó. @BrokenMan
Devesh Saini

1
@DeveshSaini Tôi đã không dành thời gian để tìm ra điều đó. Cách duy nhất mà tôi quản lý để có được một ứng dụng python + Pyside đầy đủ để biên dịch như trên, là phát triển chương trình theo cách thông thường - rất nhiều câu lệnh bao gồm <mymodule> + thử nghiệm với trình thông dịch. Sau đó, khi tất cả đã sẵn sàng, tôi dán thủ công tất cả các mã được bao gồm và nhận xét ra các câu lệnh bao gồm liên quan mà họ đã thay thế. Vâng, đó là điều không mong muốn, nhưng như tôi đã nói lúc đầu, tôi đã không dành thời gian để xem cách tôi có thể biên dịch chỉ quy trình chính và liên kết các mô-đun đi kèm với nhau.
Broken Man

3
Liên kết tĩnh của libpython thì sao?
James Mills

4
Đối với python 2.7 cython --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

17

Hãy xem các câu trả lời cho Cython có thể biên dịch thành EXE không?mà, trái với tất cả các câu trả lời khác ở đây nói rằng có, có thể biên dịch thành tệp thực thi.

Các liên kết tại Embedding Cython có vẻ là một nơi tốt để bắt đầu, nhưng đó không phải là mục đích chính của Cython nên tôi không biết nó sẽ đơn giản như thế nào.


1
Cảm ơn vì các liên kết. Tôi cũng nghi ngờ điều đó có thể xảy ra vì tôi sử dụng Python để tạo tệp .so có chứa mã thực thi.
mozza

4

Tôi không biết nếu điều này sẽ giúp ích hay không nhưng Nudzo là chính xác. Bạn có thể lấy nó bằng cython --embed -o main.o main.pyvà sau đó tôi cố gắng biên dịch kết quả bằng cl / EHsc


-21

Bạn không thể, Cython không được tạo ra để biên dịch Python cũng như biến nó thành một tệp thực thi.

Để tạo tệp .exe, hãy sử dụng py2exe .

Để tạo một gói cho Mac hoặc Linux, hãy sử dụng quy trình hệ thống đóng gói theo quy định vì không có gì cụ thể về một chương trình ngôn ngữ tập lệnh trong Unix env.


2
Nó cho phép tôi chuyển các tệp .py của mình thành tệp .so. Xem kịch bản ở trên tôi sử dụng. Các tệp .so không chứa mã thực thi?
mozza

Nó không phải là mục đích. Cython là để biên dịch các phần mở rộng Python C / C ++, không biến các tập lệnh Python thành tệp thực thi.
e-thoả mãn

9
Thông tin sai lệch. Có cython --embedthể tạo ra các tệp thực thi với Python nhúng.
nudzo

Kết quả thực thi vẫn phụ thuộc vào libpython trừ khi bạn liên kết tĩnh. Thêm vào đó, nó sẽ không tạo ra một tệp thực thi trong tất cả các tệp của bạn, nhưng một tệp thực thi từ điểm nhập của bạn.
e-thoả mãn

2
@ e-thoả mãn Có, tệp thực thi sẽ được liên kết động với phiên bản libpython mà nó được biên dịch vào thời điểm đó. Vấn đề là gì? Nếu nó dành cho Linux và nếu bạn đang lên kế hoạch phân phối ứng dụng của mình, bạn chỉ cần gói nó vào bất kỳ định dạng phân phối linux nào mà bạn đang nhắm mục tiêu - giống như mọi gói nhị phân khác. ví dụ: myapp_1_wheezy_amd64.deb sẽ là ứng dụng python đã biên dịch của bạn được liên kết với python2 hoặc python3 cho bản phân phối đó. Đối với Windows, chỉ cần cung cấp python cần thiết. Một lần nữa, tôi không nhìn thấy vấn đề ở đây, hoặc sự phản đối.
Broken Man
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.