Giới thiệu về Nuitka. Một cách tốt hơn để biên dịch và phân phối Python

Nuitka cho phép bạn dịch mã Python thành các tệp thực thi độc lập để bạn có thể chia sẻ nó mà không cần môi trường thời gian chạy Python

  • Giới thiệu về Nuitka. Một cách tốt hơn để biên dịch và phân phối Python
    Bởi Serdar Yegulalp

    Nhà văn cao cấp, InfoWorld.

    A better way to compile and distribute Python applications.

    Mục lục

    Cho xem nhiều hơn

    Khi mức độ phổ biến của Python tăng lên, những hạn chế của nó ngày càng rõ ràng hơn. Đối với một điều, có thể rất khó để viết một ứng dụng Python và phân phối nó cho những người chưa cài đặt Python

    Cách phổ biến nhất để giải quyết vấn đề này là đóng gói chương trình cùng với tất cả các thư viện và tệp hỗ trợ cũng như thời gian chạy Python. Có các công cụ để thực hiện việc này, chẳng hạn như PyInstaller, nhưng chúng yêu cầu nhiều cad để hoạt động chính xác. Hơn nữa, thường có thể trích xuất mã nguồn cho chương trình Python từ gói kết quả. Đối với một số tình huống, đó là một công cụ giảm giá

    [ Điều chỉnh Dev với Serdar để nhận các mẹo mã hóa Go và Python trong 5 phút hoặc ít hơn ]

    Nuitka, một dự án của bên thứ ba, đưa ra một giải pháp triệt để. Nó biên dịch một chương trình Python thành nhị phân C—không phải bằng cách đóng gói thời gian chạy CPython với mã byte của chương trình, mà bằng cách dịch các lệnh Python sang C. Các kết quả có thể được phân phối trong một gói nén hoặc được đóng gói thành một trình cài đặt với một sản phẩm của bên thứ ba khác

    Nuitka cũng cố gắng duy trì khả năng tương thích tối đa với hệ sinh thái Python, vì vậy các thư viện của bên thứ ba như NumPy hoạt động đáng tin cậy. Nuitka cũng cố gắng cải thiện hiệu suất cho các chương trình Python đã biên dịch bất cứ khi nào có thể, nhưng một lần nữa mà không làm mất đi khả năng tương thích tổng thể. Khả năng tăng tốc cũng không được đảm bảo—chúng khác nhau rất nhiều giữa các khối lượng công việc và một số chương trình có thể không nhận được bất kỳ cải tiến đáng kể nào về hiệu suất. Theo nguyên tắc chung, tốt nhất là không nên dựa vào Nuitka để cải thiện hiệu suất mà nên dựa vào một giải pháp trọn gói

    Cài đặt Nuitka

    Nuitka hoạt động với Python 2. 6 đến 2. 7 và Trăn 3. 3 đến 3. 10. Nó có thể biên dịch các tệp nhị phân cho Microsoft Windows, macOS, Linux và FreeBSD/NetBSD. Lưu ý rằng bạn phải xây dựng các tệp nhị phân trên nền tảng đích;

    Đối với mọi nền tảng, ngoài việc cần thời gian chạy Python, bạn cũng sẽ cần một trình biên dịch C. Trên Microsoft Windows, nên dùng Visual Studio 2022 trở lên nhưng cũng có thể sử dụng MinGW-w64 C11 (

    
    def greet(name):
        print ("Hello ", name)
    
    7 11. 2 hoặc cao hơn). Đối với các nền tảng khác, bạn có thể sử dụng
    
    def greet(name):
        print ("Hello ", name)
    
    7 5. 1 hoặc cao hơn,
    
    def greet(name):
        print ("Hello ", name)
    
    0 4. 4 trở lên,
    
    def greet(name):
        print ("Hello ", name)
    
    1 hoặc
    
    def greet(name):
        print ("Hello ", name)
    
    2 trên Windows trong Visual Studio

    Lưu ý rằng nếu bạn sử dụng Python 3. 3 hoặc Trăn 3. 4 (không còn được dùng nữa), bạn sẽ cần Python 2. 7 vì phụ thuộc vào công cụ. Tất cả điều này phải là một đối số để sử dụng phiên bản Python mới nhất nếu bạn có thể

    Tốt nhất là cài đặt Nuitka trong môi trường ảo cùng với dự án của bạn dưới dạng phụ thuộc phát triển thay vì phụ thuộc phân phối. Bản thân Nuitka không đi kèm hoặc được sử dụng bởi dự án của bạn;

    Lần đầu tiên sử dụng Nuitka

    Khi bạn đã cài đặt Nuitka, hãy sử dụng

    
    def greet(name):
        print ("Hello ", name)
    
    3 hoặc
    
    def greet(name):
        print ("Hello ", name)
    
    4 để gọi nó

    Điều đầu tiên bạn muốn làm với Nuitka là xác minh toàn bộ chuỗi công cụ hoạt động, bao gồm cả trình biên dịch C của bạn. Để kiểm tra điều này, bạn có thể biên dịch một chương trình Python "Xin chào thế giới" đơn giản—gọi nó là

    
    def greet(name):
        print ("Hello ", name)
    
    5

    
    def greet(name):
        print ("Hello ", name)
    
    2

    Khi bạn biên dịch chương trình Python với Nuitka, bạn chuyển tên của mô-đun điểm đầu vào làm tham số cho Nuitka, ví dụ:

    
    def greet(name):
        print ("Hello ", name)
    
    6. Khi được gọi như thế này, Nuitka sẽ lấy 
    
    def greet(name):
        print ("Hello ", name)
    
    5 và tạo một tệp thực thi duy nhất từ ​​đó

    Lưu ý rằng vì chúng tôi chỉ đang thử nghiệm chức năng của Nuitka, nên nó sẽ chỉ biên dịch một tệp Python đó thành tệp thực thi. Nó sẽ không biên dịch bất cứ thứ gì khác, cũng như không đóng gói bất cứ thứ gì để phân phối lại. Nhưng biên dịch một tệp là đủ để xác định xem chuỗi công cụ của Nuitka có được thiết lập chính xác hay không

    Khi quá trình biên dịch kết thúc, bạn sẽ thấy một tệp thực thi nhị phân được đặt trong cùng thư mục với chương trình Python. Chạy tệp thực thi để đảm bảo nó hoạt động

    Bạn cũng có thể tự động chạy ứng dụng do Nuitka biên dịch bằng cách chuyển

    
    def greet(name):
        print ("Hello ", name)
    
    8 dưới dạng cờ dòng lệnh

    Nếu tệp thực thi thử nghiệm "Xin chào thế giới" của bạn hoạt động, bạn có thể thử đóng gói nó dưới dạng tệp có thể phân phối lại. Tôi sẽ giải thích quá trình đó ngay sau đây

    Lưu ý rằng khi bạn chạy phần biên dịch thử nghiệm đầu tiên của mình với Nuitka, nó có thể sẽ hoàn thành sau vài giây. Đừng để bị lừa bởi điều này. Ngay bây giờ, bạn chỉ đang biên dịch một mô-đun duy nhất, không phải toàn bộ chương trình của bạn. Việc biên dịch một chương trình đầy đủ với Nuitka có thể mất nhiều phút hoặc lâu hơn, tùy thuộc vào số lượng mô-đun mà chương trình sử dụng

    Biên dịch chương trình Python với Nuitka

    Theo mặc định, Nuitka chỉ biên dịch mô-đun bạn chỉ định. Nếu mô-đun của bạn có các mục nhập—cho dù từ nơi khác trong chương trình của bạn, từ thư viện tiêu chuẩn hay từ các gói của bên thứ ba—bạn sẽ cần chỉ định rằng những mục đó cũng sẽ được biên dịch

    Hãy xem xét một phiên bản sửa đổi của chương trình "Xin chào thế giới", trong đó bạn có một mô-đun liền kề có tên là

    
    def greet(name):
        print ("Hello ", name)
    
    9

    
    def greet(name):
        print ("Hello ", name)
    

    và một

    
    def greet(name):
        print ("Hello ", name)
    
    5 đã sửa đổi

    
    def greet(name):
        print ("Hello ", name)
    
    9

    Để biên dịch cả hai mô-đun, bạn có thể sử dụng công tắc

    
    def greet(name):
        print ("Hello ", name)
    
    91

    
    def greet(name):
        print ("Hello ", name)
    
    1

    Việc chuyển đổi đảm bảo rằng tất cả các lần nhập được yêu cầu trong suốt chương trình được truy tìm từ các câu lệnh

    
    def greet(name):
        print ("Hello ", name)
    
    92 và được biên dịch cùng nhau

    Một tùy chọn khác,

    
    def greet(name):
        print ("Hello ", name)
    
    93, cho phép bạn loại trừ các thư mục con cụ thể khỏi quy trình nhập. Tùy chọn này hữu ích để sàng lọc các bộ thử nghiệm hoặc mô-đun mà bạn biết là không bao giờ được sử dụng. Nó cũng cho phép bạn cung cấp ký tự đại diện làm đối số

    Compiling a large program with Nuitka.IDG

    Hình 1. Biên dịch một chương trình lớn, phức tạp với Nuitka. Ví dụ này liên quan đến việc biên dịch mô-đun Pyglet cùng với nhiều mô-đun trong thư viện chuẩn, mất vài phút

    Bao gồm nhập động

    Bây giờ đến một trong những vấn đề mà người dùng Python thường gặp phải khi cố gắng đóng gói một ứng dụng Python để phân phối. Tùy chọn

    
    def greet(name):
        print ("Hello ", name)
    
    91 chỉ tuân theo các lần nhập được khai báo rõ ràng bằng mã bằng câu lệnh
    
    def greet(name):
        print ("Hello ", name)
    
    92. Nó không xử lý nhập động

    Để giải quyết vấn đề này, bạn có thể sử dụng công tắc

    
    def greet(name):
        print ("Hello ", name)
    
    96 để cung cấp một hoặc nhiều đường dẫn đến các mô-đun được nhập động. Chẳng hạn, đối với thư mục có tên
    
    def greet(name):
        print ("Hello ", name)
    
    97 chứa mã được nhập động, bạn sẽ sử dụng

    
    def greet(name):
        print ("Hello ", name)
    
    8

    Bao gồm các tệp dữ liệu và thư mục

    Nếu chương trình Python của bạn sử dụng các tệp dữ liệu được tải trong thời gian chạy, thì Nuitka cũng không thể tự động phát hiện các tệp đó. Để bao gồm các tệp và thư mục riêng lẻ với chương trình đóng gói Nuitka, bạn sẽ sử dụng

    
    def greet(name):
        print ("Hello ", name)
    
    98 và
    
    def greet(name):
        print ("Hello ", name)
    
    99

    
    def greet(name):
        print ("Hello ", name)
    
    98 cho phép bạn chỉ định ký tự đại diện cho các tệp sẽ sao chép và nơi bạn muốn sao chép chúng vào. Chẳng hạn,
    
    def greet(name):
        print ("Hello ", name)
    
    11 lấy tất cả các tệp khớp với ký tự đại diện
    
    def greet(name):
        print ("Hello ", name)
    
    12 và sao chép chúng vào
    
    def greet(name):
        print ("Hello ", name)
    
    13 trong thư mục phân phối của bạn

    
    def greet(name):
        print ("Hello ", name)
    
    99 hoạt động gần giống như vậy, ngoại trừ việc nó không sử dụng ký tự đại diện; . Ví dụ:
    
    def greet(name):
        print ("Hello ", name)
    
    15 sẽ sao chép mọi thứ trong
    
    def greet(name):
        print ("Hello ", name)
    
    16 vào thư mục phù hợp
    
    def greet(name):
        print ("Hello ", name)
    
    17 trong thư mục phân phối của bạn

    [ Cũng trên InfoWorld. 11 mẹo tăng tốc chương trình Python ]

    Bao gồm các gói và mô-đun Python

    Một cách khác để chỉ định nhập là sử dụng không gian tên gói kiểu Python thay vì đường dẫn tệp, sử dụng tùy chọn

    
    def greet(name):
        print ("Hello ", name)
    
    18. Chẳng hạn, lệnh sau sẽ bao gồm
    
    def greet(name):
        print ("Hello ", name)
    
    19, bất kể nó ở đâu trên đĩa (giả sử Python có thể xác định vị trí của nó) và mọi thứ bên dưới nó

    
    def greet(name):
        print ("Hello ", name)
    
    1

    Nếu các gói yêu cầu tệp dữ liệu của riêng chúng, bạn có thể bao gồm các gói đó bằng tùy chọn

    
    def greet(name):
        print ("Hello ", name)
    
    80

    
    def greet(name):
        print ("Hello ", name)
    
    3

    Lệnh này yêu cầu Nuitka chọn bất kỳ tệp nào trong thư mục gói không thực sự là mã

    Nếu bạn chỉ muốn bao gồm một mô-đun duy nhất, bạn có thể sử dụng

    
    def greet(name):
        print ("Hello ", name)
    
    81

    
    def greet(name):
        print ("Hello ", name)
    
    5

    Lệnh này yêu cầu Nuitka chỉ bao gồm

    
    def greet(name):
        print ("Hello ", name)
    
    82, ngoài ra không có gì khác

    Biên dịch chương trình Python để phân phối lại

    Khi bạn muốn biên dịch chương trình Python với Nuitka để phân phối lại, bạn có thể sử dụng công tắc dòng lệnh,

    
    def greet(name):
        print ("Hello ", name)
    
    83, xử lý hầu hết công việc. Công tắc này tự động theo dõi tất cả các lần nhập và tạo thư mục
    
    def greet(name):
        print ("Hello ", name)
    
    84 bao gồm tệp thực thi đã biên dịch và mọi tệp hỗ trợ cần thiết. Để phân phối lại chương trình, bạn chỉ cần sao chép thư mục này

    Đừng mong đợi một chương trình do

    
    def greet(name):
        print ("Hello ", name)
    
    83 biên dịch sẽ hoạt động ngay lần đầu tiên bạn chạy nó. Tính năng động chung của các chương trình Python đều đảm bảo rằng bạn sẽ cần sử dụng một số tùy chọn khác được mô tả ở trên để đảm bảo chương trình đã biên dịch chạy đúng cách. Ví dụ: nếu bạn có ứng dụng GUI yêu cầu phông chữ cụ thể, bạn có thể phải sao chép chúng vào bản phân phối của mình bằng
    
    def greet(name):
        print ("Hello ", name)
    
    98 hoặc
    
    def greet(name):
        print ("Hello ", name)
    
    99

    Ngoài ra, như đã lưu ý ở trên, thời gian biên dịch cho ứng dụng

    
    def greet(name):
        print ("Hello ", name)
    
    83 có thể dài hơn đáng kể so với thời gian biên dịch thử nghiệm. Ngân sách trong thời gian xây dựng cần thiết để thử nghiệm một ứng dụng được xây dựng độc lập sau khi bạn biết một số ý tưởng về việc sẽ mất bao lâu

    Cuối cùng, Nuitka cung cấp một tùy chọn xây dựng khác, 

    
    def greet(name):
        print ("Hello ", name)
    
    89. Đối với những người đã quen thuộc với PyInstaller, 
    
    def greet(name):
        print ("Hello ", name)
    
    89 hoạt động giống như tùy chọn tương tự trong chương trình đó. nó nén toàn bộ ứng dụng của bạn, bao gồm tất cả các tệp phụ thuộc của nó, thành một tệp thực thi duy nhất mà không cần tệp nào khác để phân phối lại. Tuy nhiên, điều quan trọng cần biết là 
    
    def greet(name):
        print ("Hello ", name)
    
    89 hoạt động khác nhau trên Linux và Microsoft Windows. Trên Linux, nó gắn một hệ thống tệp ảo với nội dung của kho lưu trữ. Trên Windows, nó giải nén các tệp vào một thư mục tạm thời và chạy chúng từ đó—và nó phải làm điều này cho mỗi lần chạy chương trình. Sử dụng 
    
    def greet(name):
        print ("Hello ", name)
    
    89 trên Windows có thể làm chậm đáng kể thời gian khởi động chương trình

    Có liên quan

    • con trăn
    • Phát triển phần mềm
    • Thư viện và Framework phát triển

    Serdar Yegulalp là một nhà văn cao cấp tại InfoWorld, tập trung vào học máy, container hóa, devops, hệ sinh thái Python và đánh giá định kỳ

    Làm cách nào để biên dịch mã Python với Nuitka?

    Khi bạn muốn biên dịch chương trình Python với Nuitka để phân phối lại, bạn có thể sử dụng một công tắc dòng lệnh, --standalone , để . Công tắc này tự động theo dõi tất cả các lần nhập và tạo một thư mục dist bao gồm tệp thực thi đã biên dịch và mọi tệp hỗ trợ cần thiết.

    Nuitka hoạt động như thế nào?

    Nuitka (phát âm là /njuːtkʌ/) là một trình biên dịch mã nguồn sang mã nguồn biên dịch mã Python thành mã nguồn C, áp dụng một số tối ưu hóa thời gian biên dịch trong quy trình như gấp và truyền liên tục, dự đoán cuộc gọi tích hợp, suy luận kiểu,

    Nuitka có nhanh không?

    Điều quan trọng cần biết là đầu ra được biên dịch của Nuitka được tối ưu hóa cao và nhanh hơn chương trình python thô , nhưng nó vẫn không .

    Làm cách nào để kiểm tra phiên bản Nuitka?

    Cài đặt Nuitka .
    python -m pip cài đặt nuitka
    Xác minh bằng lệnh python -m nuitka --version