Có cách nào để biên dịch ứng dụng python thành tệp nhị phân tĩnh không?


83

Những gì tôi đang cố gắng làm là gửi mã của tôi đến một máy chủ từ xa, máy chủ này có thể đã cài đặt phiên bản python khác và / hoặc có thể không có các gói mà ứng dụng của tôi yêu cầu.

Ngay bây giờ để đạt được tính di động như vậy, tôi phải xây dựng virtualenv có thể di dời với trình thông dịch và mã. Cách tiếp cận đó có một số vấn đề (ví dụ: bạn phải sao chép thủ công một loạt thư viện vào virtualenv của mình, vì --always-copynó không hoạt động như mong đợi) và thường chậm.

Trên lý thuyết, có một cách để tự xây dựng python một cách tĩnh.

Tôi tự hỏi liệu tôi có thể đóng gói trình thông dịch với mã của mình thành một tệp nhị phân và chạy ứng dụng của tôi dưới dạng mô-đun không. Đại loại vậy: ./mypython -m myapp runhoặc ./mypython -m gunicorn -c ./gunicorn.conf myapp.wsgi:application.


Bạn có nghĩa là một cái gì đó giống như cx_freeze?
TigerhawkT3

@ TigerhawkT3, tôi chưa bao giờ nghe nói về cx_freeze cho đến hôm nay. Xem qua tài liệu, có vẻ như đó là những gì tôi muốn, nhưng nó không thể xây dựng trên Ubuntu 12.04.5 với python3.5.1. Tôi đang tìm các giải pháp thay thế, cảm ơn vì đã đá đúng hướng.
roboslone

Đáng buồn thay, PyInstaller không làm việc với Django 1,9 và py2app / py2exe không hỗ trợ Linux :(
roboslone

2
nếu cx_Freeze và pyinstaller không hoạt động, vẫn còn hy vọng. Bạn có thể tạo (các) gói cho (các) bản phân phối mục tiêu của mình, điều này sẽ giải quyết tất cả các phụ thuộc khi cài đặt. Hoặc, có thể sử dụng một cái gì đó như docker để chạy ứng dụng của bạn.
KeatsPeeks

1
tùy chọn khác là nuitka và cython
denfromufa

Câu trả lời:


116

Có hai cách bạn có thể thực hiện để giải quyết vấn đề của mình

  1. Sử dụng trình tạo tĩnh, như đóng băng hoặc pyinstallerhoặcpy2exe
  2. Biên dịch bằng cách sử dụng cython

Tôi sẽ giải thích cách bạn có thể làm điều đó bằng cách sử dụng phương pháp thứ hai, vì phương pháp đầu tiên không phải là nền tảng và phiên bản chéo, và đã được giải thích trong các câu trả lời khác. Ngoài ra, sử dụng các chương trình như pyinstaller thường dẫn đến kích thước tệp lớn, trong đó khi sử dụng cython sẽ dẫn đến tệp có kích thước KBs

Đầu tiên, hãy cài đặt cython. Sau đó, đổi tên tệp python của bạn (giả sử test.py) thành .pyxtệp

sudo pip install cython
mv test.py test.pyx

Sau đó, bạn có thể sử dụng cythoncùng với GCC để biên dịch nó ( cythontạo tệp C từ tệp Python .pyxvà sau đó GCC biên dịch tệp C)

(tham khảo https://stackoverflow.com/a/22040484/5714445 )

cython test.pyx --embed
gcc -Os -I /usr/include/python3.5m -o test test.c -lpython3.5m -lpthread -lm -lutil -ldl

LƯU Ý : Tùy thuộc vào phiên bản python của bạn, bạn có thể phải thay đổi lệnh cuối cùng. Để biết bạn đang sử dụng phiên bản python nào, chỉ cần sử dụng

$ python -V

Bây giờ bạn sẽ có một tệp nhị phân 'kiểm tra', đó là những gì bạn đang tìm kiếm

Những điều khác cần lưu ý :

  1. Cython được sử dụng để sử dụng các định nghĩa Biến loại C để cấp phát bộ nhớ tĩnh nhằm tăng tốc các chương trình Python. Tuy nhiên, trong trường hợp của bạn, bạn vẫn sẽ sử dụng các định nghĩa Python truyền thống.
  2. Nếu bạn đang sử dụng các thư viện bổ sung (chẳng opencvhạn như), bạn có thể phải cung cấp thư mục cho họ bằng cách sử dụng -Lvà sau đó chỉ định tên của thư viện sử dụng -ltrong GCC Flags. Để biết thêm thông tin về điều này, vui lòng tham khảo cờ GCC

19
Xin chào, điều gì sẽ xảy ra nếu ứng dụng của tôi trải dài trên nhiều tệp. Cách tiếp cận này dường như chỉ biên dịch tập lệnh hiện tại chứ không phải tất cả các phụ thuộc Python.
RChat

2
không cần đổi tên tệp python của bạn (say test.py) thành pyx ngay bây giờ
iMath

3
Điều này đã giúp tôi rất nhiều. Để trả lời câu hỏi về nhiều tệp, bạn có thể sử dụng mạng: cythonize -i file_0.py [...] file_n.pycho tất cả các mô-đun python của bạn, sau đó cython main_file.py --embedcho tập lệnh chính của bạn. Bạn sẽ kết thúc với một tệp thực thi và .so (.dll, .dylib tùy thuộc vào hệ điều hành của bạn) mà bạn có thể sử dụng cùng nhau như một giải pháp độc lập.
afp

Tôi nhận được "Không có mô-đun nào có tên mã hóa". Tôi được biết rằng tôi yêu cầu một số tệp nhất định từ cài đặt python. Tuy nhiên, hệ thống mục tiêu của tôi không có python. Xin vui lòng giúp đỡ.
abhiarora

8

Bạn có thể muốn điều tra Nuitka . Nó lấy mã nguồn python và chuyển đổi nó thành các lệnh gọi API C ++. Sau đó, nó biên dịch thành một tệp nhị phân thực thi (ELF trên Linux). Nó đã xuất hiện được vài năm và hỗ trợ nhiều phiên bản Python.

Bạn cũng có thể sẽ nhận được sự cải thiện về hiệu suất nếu bạn sử dụng nó. Được đề xuất.


Tôi không thể tìm thấy bất kỳ thông tin nào về việc sử dụng Nuitka với Django. Bạn có cơ hội nào có kinh nghiệm như vậy không?
roboslone

@roboslone, Prakhar Agarwal Cython hỗ trợ thư viện bên ngoài thực sự tốt, khi so sánh với trình xây dựng tĩnh của Nuitka PyPy. Ví dụ: từ liên kết ở cuối nhận xét này, "mọi người sử dụng Cython vì nó giúp họ giải quyết vấn đề. Đó là họ muốn kết nối với các thư viện không phải Python bên ngoài từ mã Python hoặc họ muốn có thể bằng tay tối ưu hóa mã của họ, hoặc cả hai ", liên kết được. blog.behnel.de/posts/indexp241.html
RS Nikhil Krishna

1
RS Nikhil Krishna, Tôi không cố gắng làm cho mã của mình nhanh hơn, tôi đang cố gắng gửi nó ở dạng nhị phân với trình thông dịch python bên trong.
roboslone

Aah không sao. Tôi nghĩ bạn muốn liên kết nó với một số thư viện bên ngoài. Lỗi của tôi.
RS Nikhil Krishna


0

Các tùy chọn đóng băng:

Tuy nhiên, máy chủ đích của bạn phải có môi trường bạn muốn -> bạn có thể 'tạo' nó. Nếu không, bạn nên xây dựng phần mềm của mình để phù hợp với môi trường.

Tôi đã tìm thấy hướng dẫn hữu ích này về cách cài đặt phiên bản tùy chỉnh của python vào virtualenv, giả sử bạn có quyền truy cập ssh: https://stackoverflow.com/a/5507373/5616110

Trong virtualenv, bạn có thể pip cài đặt bất kỳ thứ gì và bạn không cần phải lo lắng về các đặc quyền của sudo. Tất nhiên, có những thứ đó và quyền truy cập vào trình quản lý gói như apt khiến mọi thứ dễ dàng hơn rất nhiều.


Tôi đã sử dụng virtualenv, đây không phải là trường hợp. Câu hỏi của tôi là về python được biên dịch tĩnh với các mô-đun và ứng dụng bắt buộc.
roboslone

Sau đó, bạn phải đóng băng nó, không có cách nào khác xung quanh điều đó.
iScrE4m

0

Nếu bạn đang sử dụng máy Mac, bạn có thể sử dụng py2app để tạo gói .app, gói này sẽ khởi động ứng dụng Django của bạn khi bạn nhấp đúp vào nó.

Tôi đã mô tả cách gói Django và CherryPy thành một gói như vậy tại https://moosystems.com/articles/14-distribute-django-app-as-native-desktop-app-01.html

Trong bài viết, tôi sử dụng pywebview để hiển thị trang web Django của bạn trong một cửa sổ ứng dụng cục bộ.


Ứng dụng của tôi chạy trên Linux chủ yếu, vì vậy py2app không áp dụng
roboslone

Mặc dù bài viết sử dụng py2app nhưng nó cũng có thể được thực hiện bằng pyinstaller.
André Aulich
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.