Hướng dẫn compile python to exe - biên dịch python thành exe

Mục lục bài viết:

  • Vấn đề phân phối
  • PyInstaller
  • Chuẩn bị dự án của bạn
  • Sử dụng PyInstaller
  • Sâu hơn về PyInstaller
    • File spec
    • Thư mục build
    • Thư mục dist
  • Một số lệnh tùy chỉnh
  • Kiểm tra khả năng thực thi mới của bạn
  • Gỡ lỗi thực thi PyInstaller
    • Sử dụng thiết bị đầu cuối
    • Gỡ lỗi file
    • Bản dựng thư mục đơn
    • Tùy chọn CLI bổ sung
    • Tài liệu PyInstaller bổ sung
    • Hỗ trợ phát hiện phụ thuộc
  • Hạn chế
  • Phần kết luận


Bạn có ghen tị với việc các nhà phát triển Go xây dựng một tệp thực thi và dễ dàng chuyển nó cho người dùng không? Sẽ thật tuyệt nếu người dùng của bạn có thể chạy ứng dụng của bạn mà không cần cài đặt bất cứ thứ gì? Đó là giấc mơ và PyInstaller là một cách để đạt được điều đó trong hệ sinh thái Python.

Có vô số hướng dẫn về cách thiết lập môi trường ảo, quản lý các phần phụ thuộc và xuất bản lên PyPI, điều này rất hữu ích khi bạn đang tạo các thư viện Python. Có ít thông tin hơn cho các nhà phát triển xây dựng các ứng dụng Python. Hướng dẫn này dành cho các nhà phát triển muốn phân phối ứng dụng cho người dùng có thể là nhà phát triển Python.

Trong hướng dẫn này, bạn sẽ học những điều sau:

  • Cách PyInstaller có thể đơn giản hóa việc phân phối ứng dụng
  • Cách sử dụng PyInstaller trong các dự án của riêng bạn
  • Cách gỡ lỗi PyInstaller
  • Những gì PyInstaller không làm được

PyInstaller cung cấp cho bạn khả năng tạo một thư mục hoặc tệp thực thi mà người dùng có thể chạy ngay lập tức mà không cần cài đặt thêm. Để đánh giá đầy đủ sức mạnh của PyInstaller, bạn nên xem lại một số vấn đề về phân phối mà PyInstaller giúp bạn tránh.

Vấn đề phân phối

Thiết lập một dự án Python có thể gây khó chịu, đặc biệt là đối với những người không phải là nhà phát triển. Thông thường, quá trình thiết lập bắt đầu bằng việc mở một Terminal, một thiết bị đầu cuối không dành cho một nhóm lớn người dùng tiềm năng. Kỹ thuật "rào đón - roadblock" này khiến người dùng dừng lại ngay cả trước khi hướng dẫn cài đặt đi sâu vào các chi tiết phức tạp của môi trường ảo, phiên bản Python và vô số phụ thuộc tiềm năng.

Hãy nghĩ về những gì bạn thường trải qua khi cài đặt trên một máy tính mới để phát triển Python. Nó có thể diễn ra như thế này:

  • Tải xuống và cài đặt một phiên bản Python cụ thể
  • Thiết lập pip
  • Thiết lập môi trường ảo
  • Nhận một bản sao mã của bạn
  • Cài đặt phần phụ thuộc

Hãy dừng lại một chút và xem xét xem bất kỳ bước nào ở trên có ý nghĩa gì không nếu bạn không phải là nhà phát triển, chứ đừng nói là nhà phát triển Python. Chắc là không.

Những vấn đề này phát sinh nếu người dùng của bạn đủ may mắn để truy cập vào phần phụ thuộc của cài đặt. Nhưng một số phụ thuộc vẫn yêu cầu trình biên dịch C/C++ hoặc thậm chí là FORTRAN!

Rào cản gia nhập này quá cao nếu mục tiêu của bạn là cung cấp ứng dụng cho càng nhiều người dùng càng tốt.

PyInstaller

PyInstaller tóm tắt những chi tiết này từ người dùng bằng cách tìm tất cả các phần phụ thuộc của bạn và nhóm chúng lại với nhau. Người dùng của bạn thậm chí sẽ không biết họ đang chạy một dự án Python vì bản thân Trình thông dịch Python được đóng gói vào ứng dụng của bạn. Như vậy thì PyInstaller sẽ giúp ta say goodbye các hướng dẫn cài đặt phức tạp!

PyInstaller thực hiện kỳ ​​tích tuyệt vời này bằng cách xem xét nội dung mã Python của bạn, phát hiện các phần phụ thuộc của bạn và sau đó đóng gói chúng thành một định dạng phù hợp tùy thuộc vào Hệ điều hành của bạn.

Có rất nhiều chi tiết thú vị về PyInstaller, nhưng bây giờ bạn sẽ tìm hiểu những điều cơ bản về cách hoạt động và cách sử dụng nó. Bạn luôn có thể tham khảo tài liệu PyInstaller tuyệt vời nếu bạn muốn biết thêm chi tiết.

Ngoài ra, PyInstaller có thể tạo tệp thực thi cho Windows, Linux hoặc macOS. Điều này có nghĩa là người dùng Windows sẽ nhận được một bản 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
8, người dùng Linux nhận được một tệp thực thi thông thường và người dùng macOS nhận được một gói 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
9. Có một số lưu ý cho điều này. Xem phần Hạn chế để biết thêm thông tin.

Chuẩn bị dự án của bạn

PyInstaller yêu cầu ứng dụng của bạn tuân theo một số cấu trúc tối thiểu, cụ thể là bạn phải có tập lệnh CLI để khởi động ứng dụng của mình. Thông thường, điều này có nghĩa là tạo một tập lệnh nhỏ bên ngoài gói Python của bạn tức là import gói của bạn và chạy 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
0.

Tập lệnh đầu vào là một tập lệnh Python. Về mặt kỹ thuật, bạn có thể làm bất cứ điều gì bạn muốn trong tập lệnh đầu vào, nhưng bạn nên tránh sử dụng các import tương đối. Bạn vẫn có thể sử các import tương đối trong suốt phần còn lại của ứng dụng nếu đó là kiểu bạn thích.

Lưu ý: Đầu vào là mã bắt đầu dự án hoặc ứng dụng của bạn.

Bạn có thể thử điều này với dự án của riêng mình hoặc làm theo dự án trình đọc nguồn cấp dữ liệu Python thực. Để biết thêm thông tin chi tiết bạn hãy xem hướng dẫn về Xuất bản gói trên PyPI.

Bước đầu tiên để xây dựng một phiên bản thực thi của dự án này là thêm tập lệnh điểm vào. May mắn thay, dự án trình đọc nguồn cấp dữ liệu có cấu trúc tốt, vì vậy tất cả những gì bạn cần là một tập lệnh ngắn bên ngoài gói để chạy nó. Ví dụ: bạn có thể tạo một tệp gọi là 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1 cùng với gói reader bằng mã sau:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

from reader.__main__ import main

if __name__ == '__main__':
    main()

Tập lệnh 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1 này gọi 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
0 để khởi động trình đọc nguồn cấp dữ liệu.

Việc tạo tập lệnh đầu vào này rất đơn giản khi bạn đang làm việc trong dự án của riêng mình vì bạn đã quen thuộc với mã. Tuy nhiên, việc tìm điểm đầu vào mã của người khác không dễ dàng như vậy. Trong trường hợp này, bạn có thể bắt đầu bằng cách xem tệp 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
5 trong dự án của bên thứ ba.

Tìm tham chiếu đến đối số 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
6 trong dự án 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
5. Ví dụ: đây là file 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
5 của dự án reader:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)

Như bạn có thể thấy, tập lệnh 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1 đầu vào sẽ gọi cùng một hàm được đề cập trong đối số 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
6.

Sau thay đổi này, thư mục dự án của reader sẽ trông như thế này, giả sử bạn đã kiểm tra nó vào một thư mục có tên 

$ pip install pyinstaller
2:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests

Lưu ý rằng không có thay đổi nào đối với chính mã trình đọc, chỉ là một tệp mới gọi là 

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1. Tập lệnh đầu vào này thường là tất cả những gì cần thiết để sử dụng dự án của bạn với PyInstaller.

Tuy nhiên, bạn cũng sẽ muốn tìm cách sử dụng 

$ pip install pyinstaller
5 hoặc các import bên trong các hàm. Chúng được gọi là các import ẩn trong thuật ngữ PyInstaller.

Bạn có thể chỉ định thủ công các import ẩn để buộc PyInstaller tích hợp các phụ thuộc đó nếu việc thay đổi các import trong ứng dụng của bạn quá khó. Bạn sẽ thấy cách thực hiện việc này sau trong hướng dẫn này.

Khi bạn có thể khởi chạy ứng dụng của mình bằng tập lệnh Python bên ngoài gói của mình, thì bạn đã sẵn sàng để PyInstaller thử tạo tệp thực thi.

Sử dụng PyInstaller

Bước đầu tiên là cài đặt PyInstaller từ PyPI. Bạn có thể làm điều này bằng cách sử dụng pip giống như các gói Python khác:

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

$ pip install pyinstaller

$ pip install pyinstaller
7 sẽ cài đặt phụ thuộc PyInstaller cùng với một lệnh mới: 
$ pip install pyinstaller
8. PyInstaller có thể được import bằng mã Python của bạn và được sử dụng như một thư viện, nhưng bạn có thể sẽ chỉ sử dụng nó như một công cụ CLI.

Bạn sẽ sử dụng giao diện thư viện nếu bạn tạo các tệp hook của riêng mình.

Bạn sẽ tăng khả năng mặc định của PyInstaller tạo tệp thực thi nếu bạn chỉ có các phụ thuộc Python thuần túy. Tuy nhiên, đừng quá căng thẳng nếu bạn có nhiều phụ thuộc phức tạp hơn với phần mở rộng C / C ++.

PyInstaller hỗ trợ rất nhiều gói phổ biến như NumPy, PyQt và Matplotlib mà bạn không cần thực hiện thêm bất kỳ công việc nào. Bạn có thể xem thêm về danh sách các gói mà PyInstaller chính thức hỗ trợ bằng cách tham khảo tài liệu PyInstaller.

Đừng lo lắng nếu một số phụ thuộc của bạn không được liệt kê trong tài liệu chính thức. Nhiều gói Python hoạt động tốt. Trên thực tế, PyInstaller đủ phổ biến để nhiều dự án có giải thích về cách làm cho mọi thứ hoạt động với PyInstaller.

Nói tóm lại, cơ hội để dự án của bạn hoạt động hiệu quả là rất cao.

Để thử tạo một tệp thực thi với tất cả các giá trị mặc định, chỉ cần cung cấp cho PyInstaller tên của tập lệnh đầu vào chính của bạn.

Đầu tiên, 

$ pip install pyinstaller
9 trong thư mục có đầu vào của bạn và chuyển nó làm đối số cho lệnh 
$ pip install pyinstaller
8 đã được thêm vào 
$ pyinstaller cli.py
1 khi PyInstaller được cài đặt.

Ví dụ: thực hiện lệnh sau sau khi bạn 

$ pip install pyinstaller
9 vào thư mục 
$ pip install pyinstaller
2 cấp cao nhất nếu bạn đang theo dõi cùng với dự án trình đọc nguồn cấp dữ liệu:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

$ pyinstaller cli.py

Đừng lo lắng nếu bạn thấy nhiều đầu ra trong khi xây dựng tệp thực thi của mình. PyInstaller là dài theo mặc định và độ dài có thể được tạo ra để gỡ lỗi mà bạn sẽ thấy sau.

Sâu hơn PyInstaller

PyInstaller rất phức tạp và sẽ tạo ra rất nhiều đầu ra. Vì vậy, điều quan trọng trước tiên là phải biết những gì cần tập trung vào. Cụ thể, tệp thực thi mà bạn có thể phân phối cho người dùng của mình và thông tin gỡ lỗi tiềm năng. Theo mặc định, lệnh 

$ pip install pyinstaller
8 sẽ tạo ra một số điều cần quan tâm như sau:

  • Một file 
    $ pyinstaller cli.py
    6
  • Một thư mục 
    $ pyinstaller cli.py
    7
  • Một thư mục 
    $ pyinstaller cli.py
    8

File Spec

File spec sẽ được đặt tên theo tập lệnh CLI của bạn theo mặc định. Theo dõi ví dụ trên bạn sẽ thấy một tệp có tên 

$ pyinstaller cli.py
9. Bạn sẽ thấy một file spec mặc định trông như thế nào sau khi chạy PyInstaller trên file 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

# -*- mode: python -*-

block_cipher = None

a = Analysis(['cli.py'],
             pathex=['/Users/realpython/pyinstaller/reader'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='cli',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='cli')

Tệp này sẽ được tạo tự động bằng lệnh 

$ pip install pyinstaller
8. Phiên bản của bạn sẽ có các đường dẫn khác nhau, nhưng phần lớn phải giống nhau.

Đừng lo lắng, bạn không cần phải hiểu đoạn mã trên để sử dụng PyInstaller một cách hiệu quả!

Tệp này có thể được sửa đổi và sử dụng lại để tạo tệp thực thi sau này. Bạn có thể thực hiện các bản dựng trong tương lai nhanh hơn một chút bằng cách cung cấp tệp đặc tả này thay vì tập lệnh đầu vào cho lệnh 

$ pip install pyinstaller
8.

Có một số trường hợp sử dụng cụ thể cho các tệp thông số kỹ thuật của PyInstaller. Tuy nhiên, đối với các dự án đơn giản, bạn sẽ không cần phải lo lắng về những chi tiết đó trừ khi bạn muốn tùy chỉnh nhiều cách dự án của mình được xây dựng.

Thư mục build

Thư mục 

$ pyinstaller cli.py
7 là nơi PyInstaller đặt hầu hết các siêu dữ liệu và thông tin dữ liệu nội bộ để xây dựng bản thực thi của bạn. Nội dung mặc định sẽ trông giống như sau:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html

Thư mục build có thể hữu ích để gỡ lỗi, nhưng trừ khi bạn gặp sự cố, thư mục này phần lớn có thể bị bỏ qua. Bạn sẽ tìm hiểu thêm về cách gỡ lỗi sau trong hướng dẫn này.

Thư mục dist

Sau khi xây dựng, bạn sẽ kết thúc với một thư mục 

$ pyinstaller cli.py
8 tương tự như sau:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

dist/
|
└── cli/
    └── cli

Thư 

$ pyinstaller cli.py
8 chứa các thành phần cuối cùng bạn sẽ muốn gửi đến người dùng của bạn. Bên trong thư mục 
$ pyinstaller cli.py
8, có một thư mục được đặt tên theo đầu vào của bạn. Vì vậy, trong ví dụ này, bạn sẽ có một thư mục 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
0 chứa tất cả các phụ thuộc và có thể thực thi cho ứng dụng của chúng ta. Tệp thực thi để chạy là 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
1 hoặc 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
2 nếu bạn đang sử dụng Windows.

Bạn cũng sẽ tìm thấy rất nhiều các tập tin với phần mở rộng 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
3, 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
4 và 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
5 tùy thuộc vào hệ điều hành của bạn. Đây là các thư viện được chia sẻ đại diện cho các phần phụ thuộc vào dự án của bạn mà PyInstaller đã tạo và thu thập.

Bạn sẽ muốn phân phối toàn bộ thư mục 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
0, nhưng bạn có thể đổi tên 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
7 thành tên bất kỳ theo ý bạn.

Tại thời điểm này, bạn có thể thử chạy file thực thi 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
1 nếu bạn đang làm theo cùng với ví dụ về trình đọc nguồn cấp dữ liệu.

Bạn sẽ nhận thấy rằng việc chạy tệp thực thi dẫn đến lỗi đề cập đến file 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
9. Điều này là do trình đọc nguồn cấp dữ liệu và các phụ thuộc của nó yêu cầu một số tệp dữ liệu bổ sung mà PyInstaller không biết. Để khắc phục điều đó, bạn sẽ phải thông báo cho PyInstaller rằng 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
9 là cần thiết, bạn sẽ tìm hiểu về điều này khi kiểm tra tệp thực thi mới của bạn.

Một số lệnh tùy chỉnh

PyInstaller đi kèm với rất nhiều tùy chọn có thể được cung cấp dưới dạng tệp thông số kỹ thuật hoặc tùy chọn CLI thông thường. Dưới đây, bạn sẽ tìm thấy một số tùy chọn phổ biến và hữu ích nhất.

dist/
|
└── cli/
    └── cli
1

Thay đổi tên tệp thực thi của bạn.

Đây là một cách để tránh tệp thực thi, tệp đặc tả và các thư mục được đặt tên theo tập lệnh đầu vào của bạn. 

dist/
|
└── cli/
    └── cli
1 rất hữu ích nếu bạn có thói quen đặt tên tập lệnh đầu vào của mình có dạng giống như 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1.

Bạn có thể tạo một tệp thực thi gọi là 

dist/
|
└── cli/
    └── cli
4 từ tập lệnh 
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
1 bằng một lệnh như sau:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

$ pyinstaller cli.py --name realpython

dist/
|
└── cli/
    └── cli
7

Đóng gói toàn bộ ứng dụng của bạn thành một tệp thực thi duy nhất.

Các tùy chọn mặc định tạo ra một thư mục phụ thuộc and và thực thi, trong khi 

dist/
|
└── cli/
    └── cli
7 giữ phân phối dễ dàng hơn bằng cách tạo ra chỉ một thực thi.

Tùy chọn này không có đối số. Để nhóm dự án của bạn thành một tệp duy nhất, bạn có thể xây dựng bằng một lệnh như sau:

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

$ pyinstaller cli.py --onefile

Với lệnh trên, thư mục 

$ pyinstaller cli.py
8 của bạn sẽ chỉ chứa một tệp thực thi duy nhất thay vì một thư mục có tất cả các tệp phụ thuộc trong các tệp riêng biệt.

$ pyinstaller cli.py --name realpython
1

Liệt kê nhiều mục nhập cấp cao nhất mà PyInstaller không thể tự động phát hiện.

Đây là một cách để làm việc xung quanh mã của bạn bằng cách sử dụng 

$ pyinstaller cli.py --name realpython
2 bên trong các hàm và 
$ pip install pyinstaller
5. Bạn cũng có thể sử dụng 
$ pyinstaller cli.py --name realpython
1 nhiều lần trong cùng một lệnh.

Tùy chọn này yêu cầu tên của gói mà bạn muốn đưa vào tệp thực thi của mình. Ví dụ: nếu dự án của bạn đã import thư viện requests bên trong một hàm, thì PyInstaller sẽ không tự động đưa 

$ pyinstaller cli.py --name realpython
5 vào tệp thực thi của bạn. Bạn có thể sử dụng lệnh sau để buộc 
$ pyinstaller cli.py --name realpython
5 được đưa vào:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
0

Bạn có thể chỉ định điều này nhiều lần trong lệnh build của mình, một lần cho mỗi lần import ẩn.

$ pyinstaller cli.py --name realpython
8 và 
$ pyinstaller cli.py --name realpython
9

Hướng dẫn PyInstaller chèn thêm dữ liệu hoặc tệp nhị phân vào bản dựng của bạn.

Điều này hữu ích khi bạn muốn nhóm trong các tệp cấu hình, ví dụ hoặc dữ liệu không phải mã khác. Bạn sẽ thấy một ví dụ về điều này sau nếu bạn đang theo dõi cùng với dự án trình đọc nguồn cấp dữ liệu.

$ pyinstaller cli.py --onefile
0

Loại trừ một số mô-đun được tích hợp trong tệp thực thi của bạn

Điều này rất hữu ích để loại trừ các yêu cầu chỉ dành cho nhà phát triển như framework testing chẳng hạn. Đây là một cách tuyệt vời để giữ kết quả mà trong đó bạn cung cấp cho người dùng càng nhỏ càng tốt. Ví dụ: nếu bạn sử dụng pytest, bạn có thể muốn loại trừ điều này khỏi tệp thực thi của mình:

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
1

$ pyinstaller cli.py --onefile
1

Tránh tự động mở cửa sổ bảng điều khiển để 

$ pyinstaller cli.py --onefile
2 nhật ký.

Điều này chỉ hữu ích nếu bạn đang xây dựng một ứng dụng hỗ trợ GUI. Điều này giúp bạn ẩn các chi tiết về việc triển khai của mình bằng cách cho phép người dùng không bao giờ nhìn thấy thiết bị đầu cuối.

Tương tự như tùy chọn 

dist/
|
└── cli/
    └── cli
7, 
$ pyinstaller cli.py --onefile
1 không có đối số:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
2

File

$ pyinstaller cli.py --onefile
6

Như đã đề cập trước đó, bạn có thể sử dụng lại file 

$ pyinstaller cli.py --onefile
6 được tạo tự động để tùy chỉnh thêm tệp thực thi của mình. File 
$ pyinstaller cli.py --onefile
6 là một tập lệnh (script) Python thông thường trong đó mặc định sử dụng thư viện API PyInstaller.

Vì nó là một tập lệnh Python thông thường, nên bạn có thể làm hầu hết mọi thứ bên trong nó. Bạn có thể tham khảo tài liệu tệp PyInstaller Spec chính thức để biết thêm thông tin về API này.

Kiểm tra khả năng thực thi mới của bạn

Cách tốt nhất để kiểm tra tệp thực thi mới của bạn là trên một máy mới. Máy mới phải có cùng hệ điều hành với máy bản dựng của bạn. Lý tưởng nhất là máy này càng giống với những gì người dùng của bạn sử dụng càng tốt. Điều đó có thể không phải lúc nào cũng có thể thực hiện được, vì vậy điều tốt nhất tiếp theo là thử nghiệm trên máy của chính bạn.

Điều quan trọng là chạy tệp thực thi kết quả mà không cần kích hoạt môi trường phát triển của bạn. Điều này có nghĩa chạy mà không có 

$ pyinstaller cli.py --onefile
9, 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
00 hoặc bất kỳ môi trường nào có thể truy cập cài đặt Python của bạn. Hãy nhớ rằng, một trong những mục tiêu chính của tệp thực thi do PyInstaller tạo là để người dùng không cần cài đặt bất kỳ thứ gì trên máy của họ.

Tiếp theo với ví dụ về trình đọc nguồn cấp dữ liệu, bạn sẽ nhận thấy rằng việc chạy file thực thi 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
7 mặc định trong thư mục 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
0 sẽ không thành công. May mắn thay, lỗi sau sẽ chỉ cho bạn vấn đề:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
3

Gói 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
04 đòi hỏi một file 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
9. Bạn có thể thêm file này vào bản dựng bằng tùy chọn 
$ pyinstaller cli.py --name realpython
8. Dưới đây là một ví dụ về cách đưa vào file 
build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
9 được yêu cầu :
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
4

Lệnh này yêu cầu PyInstaller đưa file 

build/
|
└── cli/
    ├── Analysis-00.toc
    ├── base_library.zip
    ├── COLLECT-00.toc
    ├── EXE-00.toc
    ├── PKG-00.pkg
    ├── PKG-00.toc
    ├── PYZ-00.pyz
    ├── PYZ-00.toc
    ├── warn-cli.txt
    └── xref-cli.html
9 vào thư mục 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
04 trong một thư mục mới trong bản dựng của bạn có tên 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
04.

Lưu ý: Các lệnh pyinstaller sử dụng ký tự \ để làm cho lệnh dễ đọc hơn. Bạn có thể bỏ qua \ khi tự chạy các lệnh hoặc sao chép và dán các lệnh như bên dưới miễn là bạn đang sử dụng các đường dẫn giống nhau.

Bạn sẽ muốn điều chỉnh đường dẫn trong lệnh trên để phù hợp với nơi bạn đã cài đặt phần phụ thuộc của trình đọc nguồn cấp dữ liệu.

Bây giờ chạy tệp thực thi mới sẽ dẫn đến lỗi mới về file 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
12.

Tệp này được yêu cầu bởi dự án trình đọc nguồn cấp dữ liệu, vì vậy bạn cần đảm bảo đưa nó vào bản dựng của mình:

reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
5

Một lần nữa, bạn sẽ cần điều chỉnh đường dẫn đến tệp dựa trên nơi bạn có dự án trình đọc nguồn cấp dữ liệu.

Tại thời điểm này, bạn sẽ có một tệp thực thi đang hoạt động có thể được cung cấp trực tiếp cho người dùng!

Gỡ lỗi thực thi PyInstaller

Như bạn đã thấy ở trên, bạn có thể gặp sự cố khi chạy tệp thực thi của mình. Tùy thuộc vào mức độ phức tạp của dự án của bạn, các bản sửa lỗi có thể đơn giản như bao gồm các tệp dữ liệu như ví dụ về trình đọc nguồn cấp dữ liệu. Tuy nhiên, đôi khi bạn cần nhiều kỹ thuật gỡ lỗi hơn.

Dưới đây là một số chiến lược phổ biến không theo thứ tự cụ thể. Thông thường, một trong những chiến lược này hoặc sự kết hợp sẽ dẫn đến đột phá trong các phiên gỡ lỗi khó khăn.

Sử dụng thiết bị đầu cuối

Đầu tiên, hãy thử chạy tệp thực thi từ một thiết bị đầu cuối để bạn có thể xem tất cả kết quả đầu ra.

Hãy nhớ xóa cờ build 

$ pyinstaller cli.py --onefile
1 để xem tất cả 
$ pyinstaller cli.py --onefile
2 trong cửa sổ bảng điều khiển. Thông thường, bạn sẽ thấy các ngoại lệ 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
16 nếu thiếu một phần phụ thuộc.

Gỡ lỗi file

Kiểm tra file 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
17 xem có vấn đề gì không. PyInstaller tạo ra nhiều đầu ra để giúp bạn hiểu chính xác những gì nó đang tạo. Tìm hiểu xung quanh thư mục 
$ pyinstaller cli.py
7 là một nơi tuyệt vời để bắt đầu.

Bản dựng thư mục đơn

Sử dụng chế độ phân phối 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
19 để tạo thư mục phân phối thay vì một tệp thực thi duy nhất. Một lần nữa, đây là chế độ mặc định. Xây dựng với 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
19 cung cấp cho bạn cơ hội để kiểm tra tất cả các phụ thuộc được đưa vào thay vì mọi thứ được ẩn trong một tệp thực thi duy nhất.

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
19 rất hữu ích để gỡ lỗi, nhưng 
dist/
|
└── cli/
    └── cli
7 thường dễ hiểu hơn. Sau khi gỡ lỗi, bạn có thể muốn chuyển sang chế độ 
dist/
|
└── cli/
    └── cli
7 để đơn giản hóa việc phân phối.

Tùy chọn CLI bổ sung

PyInstaller cũng có các tùy chọn để kiểm soát lượng thông tin được in ra trong quá trình xây dựng. Xây dựng lại tệp thực thi với tùy chọn 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
24 và xem lại kết quả đầu ra.

PyInstaller sẽ tạo ra nhiều đầu ra khi tăng độ dài với 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
24. Sẽ rất hữu ích khi lưu đầu ra này vào một tệp mà bạn có thể tham khảo sau này thay vì đặt trong Terminal của bạn. Để làm điều này, bạn có thể sử dụng chức năng chuyển hướng của trình bao . Đây là một ví dụ:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
6

Bằng cách sử dụng lệnh trên, bạn sẽ có một tệp được gọi là 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
27 chứa nhiều thông điệp 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
28 bổ sung.

Lưu ý: Chuyển hướng tiêu chuẩn với > là không đủ. PyInstaller in ra luồng stderr chứ không phải stdout . Điều này có nghĩa là bạn cần chuyển hướng luồng stderr đến một tệp, có thể được thực hiện bằng cách sử dụng 2 như trong lệnh trước.

Dưới đây là ví dụ về file 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
27 của bạn có thể trông như thế nào:
reader/
|
├── reader/
|   ├── __init__.py
|   ├── __main__.py
|   ├── config.cfg
|   ├── feed.py
|   └── viewer.py
|
├── cli.py
├── LICENSE
├── MANIFEST.in
├── README.md
├── setup.py
└── tests
2

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
7

Tệp này sẽ có nhiều thông tin chi tiết về những gì được đưa vào trong bản dựng của bạn, tại sao một số thứ không được đưa vào và cách tệp thực thi được đóng gói.

Bạn cũng có thể xây dựng lại tệp thực thi của mình bằng cách sử dụng tùy chọn 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
31 ngoài việc sử dụng tùy chọn 
setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
32 để biết thêm thông tin.

Lưu ý: Các tùy chọn -y và --clean hữu ích khi xây dựng lại, đặc biệt là khi định cấu hình ban đầu các bản dựng hoặc công trình của bạn bằng Tích hợp Liên tục. Các tùy chọn này loại bỏ các bản dựng cũ và loại bỏ nhu cầu nhập của người dùng trong quá trình xây dựng.

Tài liệu PyInstaller bổ sung

PyInstaller GitHub Wiki có rất nhiều liên kết hữu ích và các mẹo gỡ rối. Đáng chú ý nhất là các phần về đảm bảo mọi thứ được đóng gói chính xác và phải làm gì nếu mọi thứ xảy ra sai sót.

Hỗ trợ phát hiện phụ thuộc

Vấn đề phổ biến nhất bạn sẽ thấy là ngoại lệ 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
16 nếu PyInstaller không thể phát hiện đúng tất cả các phần phụ thuộc của bạn. Như đã đề cập trước đây, điều này có thể xảy ra nếu bạn đang sử dụng 
$ pip install pyinstaller
5, import các hàm bên trong hoặc các loại import ẩn khác.

Nhiều loại sự cố này có thể được giải quyết bằng cách sử dụng tùy chọn 

$ pyinstaller cli.py --name realpython
1. Điều này yêu cầu PyInstaller đưa vào một mô-đun hoặc gói ngay cả khi nó không tự động phát hiện ra nó. Đây là cách dễ nhất để giải quyết rất nhiều phép import động trong ứng dụng của bạn.

Một cách khác để giải quyết các vấn đề là móc tệp. Các tệp này chứa thông tin bổ sung để giúp PyInstaller đóng gói phần phụ thuộc. Bạn có thể viết các hook của riêng mình và yêu cầu PyInstaller sử dụng chúng với tùy chọn CLI 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
36.

Các tệp hook là cách PyInstaller tự hoạt động bên trong nên bạn có thể tìm thấy nhiều tệp hook mẫu trong mã nguồn PyInstaller.

Hạn chế

PyInstaller cực kỳ mạnh mẽ, nhưng nó có một số hạn chế. Một số hạn chế đã được thảo luận đến: import ẩn và import tương đối trong tập lệnh đầu vào.

PyInstaller hỗ trợ tạo tệp thực thi cho Windows, Linux và macOS, nhưng không thể biên dịch chéo. Do đó, bạn không thể thực hiện nhắm mục tiêu một Hệ điều hành từ Hệ điều hành khác. Vì vậy, để phân phối các tệp thực thi cho nhiều loại HĐH, bạn sẽ cần một máy xây dựng cho mỗi HĐH được hỗ trợ.

Liên quan đến giới hạn biên dịch chéo, thật hữu ích khi biết rằng về mặt kỹ thuật PyInstaller không đóng gói hoàn toàn mọi thứ mà ứng dụng của bạn cần để chạy. Tệp thực thi của bạn vẫn phụ thuộc vào người dùng glibc. Thông thường, bạn có thể khắc phục hạn chế 

setup(
    name="realpython-reader",
    version="1.0.0",
    description="Read the latest Real Python tutorials",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/realpython/reader",
    author="Real Python",
    author_email="",
    license="MIT",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
    ],
    packages=["reader"],
    include_package_data=True,
    install_requires=[
        "feedparser", "html2text", "importlib_resources", "typing"
    ],
    entry_points={"console_scripts": ["realpython=reader.__main__:main"]},
)
37 bằng cách xây dựng trên phiên bản cũ nhất của mỗi hệ điều hành mà bạn định nhắm mục tiêu.

Ví dụ: nếu bạn muốn nhắm mục tiêu một loạt các máy Linux, thì bạn có thể xây dựng trên phiên bản CentOS cũ hơn. Điều này sẽ cung cấp cho bạn khả năng tương thích với hầu hết các phiên bản mới hơn phiên bản bạn xây dựng. Đây là chiến lược tương tự được mô tả trong PEP 0513 và là những gì PyPA khuyến nghị để xây dựng các wheel tương thích.

Trên thực tế, bạn có thể muốn tìm hiểu bằng cách sử dụng hình ảnh docker manylinux của PyPA cho môi trường xây dựng Linux của bạn. Bạn có thể bắt đầu với hình ảnh cơ sở sau đó cài đặt PyInstaller cùng với tất cả các phần phụ thuộc của mình và có một hình ảnh xây dựng hỗ trợ hầu hết các biến thể của Linux.

Phần kết luận

PyInstaller có thể giúp làm cho các tài liệu cài đặt phức tạp trở nên không cần thiết. Thay vào đó, người dùng của bạn có thể chỉ cần chạy tệp thực thi của bạn để bắt đầu nhanh nhất có thể. Quy trình làm việc của PyInstaller có thể được tóm tắt bằng cách thực hiện như sau:

  1. Tạo một tập lệnh đầu vào gọi hàm chính của bạn.
  2. Cài đặt PyInstaller.
  3. Chạy PyInstaller trên đầu vào của bạn.
  4. Kiểm tra tệp thực thi mới của bạn.
  5. Gửi kết quả thư mục 
    $ pyinstaller cli.py
    8 của bạn cho người dùng.

Người dùng của bạn không cần phải biết bạn đã sử dụng phiên bản Python nào hoặc ứng dụng của bạn có sử dụng Python!