Hướng dẫn how are packages managed in python? - các gói được quản lý trong python như thế nào?

Chỉ số gói Python (PYPI) chỉ ra một loạt các thư viện và ứng dụng tuyệt vời bao gồm mọi trường hợp sử dụng có thể tưởng tượng được. Tuy nhiên, khi nói đến việc cài đặt và sử dụng các gói này, những người mới đến thường thấy mình gặp phải các vấn đề bị thiếu quyền, phụ thuộc thư viện không tương thích và các cài đặt bị phá vỡ theo những cách đáng ngạc nhiên.

Zen of Python tuyên bố: "Nên có một người và tốt nhất là chỉ có một cách rõ ràng để làm điều đó." Điều này chắc chắn không phải lúc nào cũng đúng khi cài đặt các gói Python. Tuy nhiên, có một số công cụ và phương pháp có thể được coi là thực tiễn tốt nhất. Biết những điều này có thể giúp bạn chọn đúng công cụ cho tình huống phù hợp.

Cài đặt ứng dụng toàn hệ thống

PIP là người quản lý gói thực tế trong thế giới Python. Nó có thể cài đặt các gói từ nhiều nguồn, nhưng PYPI là nguồn gói chính nơi nó được sử dụng. Khi cài đặt các gói, PIP trước tiên sẽ giải quyết các phụ thuộc, kiểm tra xem chúng có được cài đặt trên hệ thống không và, nếu không, cài đặt chúng. Khi tất cả các phụ thuộc đã được thỏa mãn, nó sẽ tiến hành cài đặt (các) gói được yêu cầu. Tất cả điều này xảy ra trên toàn cầu, theo mặc định, cài đặt mọi thứ lên máy ở một vị trí phụ thuộc vào hệ điều hành duy nhất. is the de facto package manager in the Python world. It can install packages from many sources, but PyPI is the primary package source where it's used. When installing packages, pip will first resolve the dependencies, check if they are already installed on the system, and, if not, install them. Once all dependencies have been satisfied, it proceeds to install the requested package(s). This all happens globally, by default, installing everything onto the machine in a single, operating system-dependent location.

Python 3.7 tìm kiếm các gói trên hệ thống Arch Linux ở các vị trí sau:

$ python3.7 -c "import sys; print('\n'.join(sys.path))"

/usr/lib/python37.zip
/usr/lib/python3.7
/usr/lib/python3.7/lib-dynload
/usr/lib/python3.7/site-packages

Một vấn đề với các cài đặt toàn cầu là chỉ có thể cài đặt một phiên bản duy nhất của gói cho một trình thông dịch python nhất định. Điều này có thể gây ra các vấn đề khi gói là sự phụ thuộc của nhiều thư viện hoặc ứng dụng, nhưng chúng yêu cầu các phiên bản khác nhau của sự phụ thuộc này. Ngay cả khi mọi thứ dường như hoạt động tốt, có thể việc nâng cấp sự phụ thuộc (thậm chí vô tình trong khi cài đặt một gói khác) sẽ phá vỡ các ứng dụng hoặc thư viện này trong tương lai.

Một vấn đề tiềm năng khác là hầu hết các phân phối giống như Unix quản lý các gói Python với trình quản lý gói tích hợp (DNF, APT, Pacman, Brew, v.v.) và một số công cụ này được cài đặt vào vị trí không thể viết được của người dùng.dnf, apt, pacman, brew, and so on), and some of these tools install into a non-user-writeable location.

$ python3.7 -m pip install pytest
Collecting pytest
Downloading...
[...]
Installing collected packages: atomicwrites, pluggy, py, more-itertools, pytest
Could not install packages due to an EnvironmentError: [Error 13] Permission denied:
'/usr/lib/python3.7/site-packages/site-packages/atomicwrites-x.y.z.dist-info'
Consider using '--user' option or check the permissions.
$

Điều này không thành công vì chúng tôi đang chạy Cài đặt PIP với tư cách là người dùng không root và chúng tôi không có quyền ghi vào thư mục trang web.pip install as a non-root user and we don't have write permission to the site-packages directory.

Về mặt kỹ thuật, bạn có thể vượt qua điều này bằng cách chạy PIP như một gốc (sử dụng lệnh sudo) hoặc người dùng quản trị. Tuy nhiên, một vấn đề là chúng tôi vừa cài đặt một loạt các gói Python vào một vị trí mà Trình quản lý gói phân phối Linux sở hữu, làm cho cơ sở dữ liệu nội bộ của nó và cài đặt không nhất quán. Điều này có thể sẽ gây ra các vấn đề bất cứ lúc nào chúng tôi cố gắng cài đặt, nâng cấp hoặc xóa bất kỳ phụ thuộc nào trong số các phụ thuộc này bằng cách sử dụng trình quản lý gói.pip as a root (using the sudo command) or administrative user. However, one problem is that we just installed a bunch of Python packages into a location the Linux distribution's package manager owns, making its internal database and the installation inconsistent. This will likely cause issues anytime we try to install, upgrade, or remove any of these dependencies using the package manager.

Ví dụ, chúng ta hãy cố gắng cài đặt PyTest một lần nữa, nhưng bây giờ sử dụng trình quản lý gói hệ thống của tôi, Pacman:pytest again, but now using my system's package manager, pacman:

$ sudo pacman -S community/python-pytest
resolving dependencies...
looking for conflicting packages...
[...]
python-py: /usr/lib/site-packages/py/_pycache_/_metainfo.cpython-37.pyc exists in filesystem
python-py: /usr/lib/site-packages/py/_pycache_/_builtin.cpython-37.pyc exists in filesystem
python-py: /usr/lib/site-packages/py/_pycache_/_error.cpython-37.pyc exists in filesystem

Một vấn đề tiềm năng khác là một hệ điều hành có thể sử dụng Python cho các công cụ hệ thống và chúng ta có thể dễ dàng phá vỡ chúng bằng cách sửa đổi các gói Python bên ngoài Trình quản lý gói hệ thống. Điều này có thể dẫn đến một hệ thống không thể hoạt động, trong đó khôi phục từ bản sao lưu hoặc cài đặt lại hoàn toàn là cách duy nhất để khắc phục nó.

Cài đặt sudo pip: một ý tưởng tồi

Có một lý do khác tại sao chạy cài đặt PIP dưới dạng gốc là một ý tưởng tồi. Để giải thích điều này, trước tiên chúng ta phải xem xét các thư viện và ứng dụng Python được đóng gói như thế nào.pip install as root is a bad idea. To explain this, we first have to look at how Python libraries and applications are packaged.

Hầu hết các thư viện và ứng dụng Python ngày nay sử dụng setuptools làm hệ thống xây dựng của họ. Setuptools yêu cầu một tệp setup.py trong gốc của dự án, mô tả siêu dữ liệu gói và có thể chứa mã python tùy ý để tùy chỉnh quy trình xây dựng. Khi một gói được cài đặt từ phân phối nguồn, tệp này được thực thi để thực hiện cài đặt và thực hiện các tác vụ như kiểm tra hệ thống, xây dựng gói, v.v.setuptools as their build system. setuptools requires a setup.py file in the root of the project, which describes package metadata and can contain arbitrary Python code to customize the build process. When a package is installed from the source distribution, this file is executed to perform the installation and execute tasks like inspecting the system, building the package, etc.

Thực hiện setup.py với các quyền root có nghĩa là chúng ta có thể mở một cách hiệu quả hệ thống cho mã hoặc lỗi độc hại. Điều này có nhiều khả năng hơn bạn nghĩ. Ví dụ, vào năm 2017, một số gói đã được tải lên PYPI với các tên giống như các thư viện Python phổ biến. Mã được tải lên hệ thống được thu thập và thông tin người dùng và tải nó lên một máy chủ từ xa. Các gói này đã được kéo ngay sau đó. Tuy nhiên, các loại sự cố "đánh máy đánh máy" này có thể xảy ra bất cứ lúc nào vì bất kỳ ai cũng có thể tải các gói lên PYPI và không có quy trình đánh giá nào để đảm bảo mã không gây hại.setup.py with root permissions means we can effectively open up the system to malicious code or bugs. This is a lot more likely than you might think. For example, in 2017, several packages were uploaded to PyPI with names resembling popular Python libraries. The uploaded code collected system and user information and uploaded it to a remote server. These packages were pulled shortly thereafter. However, these kinds of "typo-squatting" incidents can happen anytime since anyone can upload packages to PyPI and there is no review process to make sure the code doesn't do any harm.

Quỹ phần mềm Python (PSF) gần đây đã thông báo rằng họ sẽ tài trợ cho hoạt động để cải thiện tính bảo mật của PYPI. Điều này sẽ làm cho việc thực hiện các cuộc tấn công như "pytosquating" khó khăn hơn và hy vọng làm cho điều này trở thành một vấn đề ít hơn trong tương lai.

Các vấn đề bảo mật sang một bên, Sudo Pip Install sẽ không giải quyết tất cả các vấn đề phụ thuộc: Bạn vẫn chỉ có thể cài đặt một phiên bản duy nhất của bất kỳ thư viện nào, điều đó có nghĩa là vẫn dễ dàng phá vỡ các ứng dụng theo cách này.sudo pip install won't solve all the dependency problems: you can still install only a single version of any given library, which means it's still easy to break applications this way.

Hãy xem xét một số lựa chọn thay thế tốt hơn.

Người quản lý gói hệ điều hành

Rất có khả năng Trình quản lý gói "gốc" mà chúng tôi sử dụng trên hệ điều hành lựa chọn của chúng tôi cũng có thể cài đặt các gói Python. Câu hỏi là: Chúng ta nên sử dụng PIP, hoặc APT, DNF, Pacman, v.v.pip, or apt, dnf, pacman, and so on?

Câu trả lơi con phụ thuộc vao nhiêu thư.

PIP thường được sử dụng để cài đặt các gói trực tiếp từ PYPI và các tác giả gói Python thường tải lên các gói của họ ở đó. Tuy nhiên, hầu hết các nhà bảo trì gói sẽ không sử dụng PYPI mà thay vào đó lấy mã nguồn từ phân phối nguồn (SDist) do tác giả hoặc hệ thống kiểm soát phiên bản (ví dụ: GitHub), áp dụng các bản vá nếu cần và kiểm tra và phát hành gói cho nền tảng tương ứng của họ. So với mô hình phân phối PYPI, điều này có ưu và nhược điểm: is generally used to install packages directly from PyPI, and Python package authors usually upload their packages there. However, most package maintainers will not use PyPI, but instead take the source code from the source distribution (sdist) created by the author or a version control system (e.g., GitHub), apply patches if needed, and test and release the package for their respective platforms. Compared to the PyPI distribution model, this has pros and cons:

  • Phần mềm được duy trì bởi các nhà quản lý gói gốc thường ổn định hơn và thường hoạt động tốt hơn trên nền tảng đã cho (mặc dù điều này có thể không phải lúc nào cũng như vậy).
  • Điều này cũng có nghĩa là nó cần thêm công việc để đóng gói và kiểm tra mã Python ngược dòng:
    1. Lựa chọn gói thường nhỏ hơn nhiều so với những gì PYPI cung cấp.
    2. Cập nhật chậm hơn và người quản lý gói thường sẽ gửi các phiên bản cũ hơn nhiều.

Nếu gói chúng tôi muốn sử dụng có sẵn và chúng tôi không bận tâm đến các phiên bản cũ hơn một chút, Trình quản lý gói cung cấp một cách thuận tiện và an toàn để cài đặt các gói Python. Và, vì các gói này cài đặt toàn hệ thống, chúng có sẵn cho tất cả người dùng trên hệ thống. Điều này cũng có nghĩa là chúng ta chỉ có thể sử dụng chúng nếu chúng ta có các quyền cần thiết để cài đặt các gói trên hệ thống.

Nếu chúng tôi muốn sử dụng thứ gì đó không có sẵn trong lựa chọn của Trình quản lý gói hoặc quá cũ hoặc chúng tôi đơn giản là không có quyền cần thiết để cài đặt các gói, chúng tôi có thể sử dụng PIP thay thế.pip instead.

Cài đặt sơ đồ người dùng

PIP hỗ trợ chế độ "sơ đồ người dùng" được giới thiệu trong Python 2.6. Điều này cho phép các gói được cài đặt vào vị trí thuộc sở hữu của người dùng. Trên Linux, điều này thường là ~/.Local. Đặt ~/.Local/bin/trên đường dẫn của chúng tôi sẽ giúp có thể có các công cụ và tập lệnh Python có sẵn trong tầm tay của chúng tôi và quản lý chúng mà không cần đặc quyền gốc. supports the "user scheme" mode introduced in Python 2.6. This allows for packages to be installed into a user-owned location. On Linux, this is typically ~/.local. Putting ~/.local/bin/ on our PATH will make it possible to have Python tools and scripts available at our fingertips and manage them without root privileges.

$ python3.7 -m pip install --user black
Collecting black
 Using cached
[...]
Installing collected packages: click, toml, black
 The scripts black and blackd are installed in '/home/tux/.local/bin' which is not on PATH.
 Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed black-x.y click-x.y toml-x.y.z
$

Tuy nhiên, giải pháp này không giải quyết được vấn đề nếu và khi chúng ta cần các phiên bản khác nhau của cùng một gói.

Nhập môi trường ảo

Môi trường ảo cung cấp các cài đặt gói Python bị cô lập có thể cùng tồn tại độc lập trên cùng một hệ thống. Điều này mang lại lợi ích tương tự như cài đặt sơ đồ người dùng, nhưng nó cũng cho phép tạo các cài đặt Python khép kín trong đó một ứng dụng không chia sẻ phụ thuộc với bất kỳ ứng dụng nào khác. VirtualEnv tạo ra một thư mục chứa một bản cài đặt Python khép kín, bao gồm các công cụ nhị phân và thiết yếu của Python để quản lý gói: setuptools, pip và bánh xe.Virtualenv creates a directory that holds a self-contained Python installation, including the Python binary and essential tools for package management: setuptools, pip, and wheel.

Tạo môi trường ảo

VirtualEnv là gói của bên thứ ba, nhưng Python 3.3 đã thêm gói VENV vào thư viện tiêu chuẩn. Do đó, chúng tôi không phải cài đặt bất cứ thứ gì để sử dụng môi trường ảo trong các phiên bản hiện đại của Python. Chúng ta chỉ có thể sử dụng Python3.7 -M VENV để tạo ra một môi trường ảo mới. is a third-party package, but Python 3.3 added the venv package to the standard library. As a result, we don't have to install anything to use virtual environments in modern versions of Python. We can simply use python3.7 -m venv to create a new virtual environment.

Sau khi tạo ra một môi trường ảo mới, chúng ta phải kích hoạt nó bằng cách tìm nguồn cung cấp tập lệnh kích hoạt trong thư mục bin của môi trường mới được tạo. Tập lệnh kích hoạt tạo ra một Subshell mới và thêm thư mục bin vào biến môi trường đường dẫn, cho phép chúng tôi chạy các nhị phân và tập lệnh từ vị trí này. Điều này có nghĩa là Subshell này sẽ sử dụng Python, PIP hoặc bất kỳ công cụ nào khác được cài đặt ở vị trí này thay vì các công cụ được cài đặt trên toàn cầu trên hệ thống.activate script in the bin directory of the newly created environment. The activation script creates a new subshell and adds the bin directory to the PATH environment variable, enabling us to run binaries and scripts from this location. This means that this subshell will use python, pip, or any other tool installed in this location instead of the ones installed globally on the system.

$ python3.7 -m venv test-env
$ . ./test-env/bin/activate
(test-env) $

Sau đó, bất kỳ lệnh nào chúng tôi thực thi sẽ sử dụng cài đặt Python bên trong môi trường ảo. Hãy cài đặt một số gói.

(test-env)$ python3.7 -m pip install --user black
Collecting black
 Using cached
[...]
Installing collected packages: click, toml, black
Successfully installed black-x.y click-x.y toml-x.y.z
(test-env) $

Chúng ta có thể sử dụng màu đen bên trong môi trường ảo mà không có bất kỳ thay đổi thủ công nào đối với các biến môi trường như đường dẫn hoặc pythonpath.black inside the virtual environment without any manual changes to the environment variables like PATH or PYTHONPATH.

(test-env) $ black --version
black, version x.y
(test-env) $ which black
/home/tux/test-env/bin/black
(test-env) $

Khi chúng ta được thực hiện với môi trường ảo, chúng ta chỉ có thể hủy kích hoạt nó với chức năng vô hiệu hóa.deactivate function.

(test-env) $ deactivate
$

Môi trường ảo cũng có thể được sử dụng mà không cần tập lệnh kích hoạt. Các tập lệnh được cài đặt trong VENV sẽ được viết lại dòng Shebang của họ để sử dụng trình thông dịch Python bên trong môi trường ảo. Bằng cách này, chúng ta có thể thực thi tập lệnh từ bất cứ nơi nào trên hệ thống bằng cách sử dụng toàn bộ đường dẫn đến tập lệnh.venv will have their shebang line rewritten to use the Python interpreter inside the virtual environment. This way, we can execute the script from anywhere on the system using the full path to the script.

(test-env) $ head /home/tux/test-env/bin/black
#!/home/tux/test-env/bin/python3.7

# -*- coding: utf-8 -*-
import re
import sys

from black import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
(test-env) $

Chúng ta chỉ có thể chạy ~/test-env/bin/đen từ bất cứ đâu trên hệ thống và nó sẽ hoạt động tốt.~/test-env/bin/black from anywhere on the system and it will work just fine.

Nó có thể hữu ích để thêm một số môi trường ảo thường được sử dụng vào biến môi trường đường dẫn để chúng tôi có thể nhanh chóng và dễ dàng sử dụng các tập lệnh trong chúng mà không cần gõ đường dẫn đầy đủ:PATH environment variable so we can quickly and easily use the scripts in them without typing out the full path:

export PATH=$PATH:~/test-env/bin

Bây giờ khi chúng ta thực hiện màu đen, nó sẽ được chọn từ môi trường ảo (trừ khi nó xuất hiện ở một nơi khác sớm hơn trên đường dẫn). Thêm dòng này vào tệp khởi tạo của shell của bạn (ví dụ: ~/.bashrc) để nó tự động đặt trong tất cả các shell mới.black, it will be picked up from the virtual environment (unless it appears somewhere else earlier on the PATH). Add this line to your shell's initialization file (e.g., ~/.bashrc) to have it automatically set in all new shells.

Môi trường ảo được sử dụng rất phổ biến để phát triển Python vì mỗi dự án có môi trường riêng, nơi tất cả các phụ thuộc thư viện có thể được cài đặt mà không can thiệp vào việc cài đặt hệ thống.

Tôi khuyên bạn nên kiểm tra dự án VirtualEnvWrapper, có thể giúp đơn giản hóa các quy trình công việc dựa trên ảo thông thường.virtualenv-based workflows.

Còn Conda thì sao?

Conda là một công cụ quản lý gói có thể cài đặt các gói do Anaconda cung cấp trên kho lưu trữ repo.continuum.io. Nó đã trở nên rất phổ biến, đặc biệt là đối với khoa học dữ liệu. Nó cung cấp một cách dễ dàng để tạo và quản lý môi trường và cài đặt các gói trong đó. Một nhược điểm so với PIP là lựa chọn gói nhỏ hơn nhiều.pip is that the package selection is much smaller.

Một công thức để quản lý gói thành công

  • Không bao giờ chạy cài đặt sudo pip.sudo pip install.
  • Nếu bạn muốn cung cấp một gói cho tất cả người dùng máy, bạn có quyền đúng và gói có sẵn, sau đó sử dụng trình quản lý gói phân phối của bạn (APT, YUM, PACMAN, BREW, v.v.).apt, yum, pacman, brew, etc.).
  • Nếu bạn không có quyền root hoặc trình quản lý gói hệ điều hành không có gói bạn cần, hãy sử dụng PIP Install --User và thêm thư mục cài đặt người dùng vào biến môi trường đường dẫn.pip install --user and add the user installation directory to the PATH environment variable.
  • Nếu bạn muốn nhiều phiên bản của cùng một thư viện cùng tồn tại, để thực hiện phát triển Python hoặc chỉ để cô lập các phụ thuộc vì bất kỳ lý do nào khác, hãy sử dụng môi trường ảo.

Bài viết này ban đầu được xuất bản vào tháng 4 năm 2019 và đã được biên tập viên cập nhật.

Các gói Python được tổ chức như thế nào?

Các gói trong các gói Python Nhóm các mô -đun tương tự trong một thư mục riêng biệt.Chúng là các thư mục chứa các mô-đun liên quan và tệp __init__.py được sử dụng để khởi tạo cấp độ gói tùy chọn.__init__.py được thực thi một lần khi một mô -đun bên trong gói được tham chiếu.Packages group similar modules in a separate directory. They are folders containing related modules and an __init__.py file which is used for optional package-level initialisation. __init__.py is executed once when a module inside the package is referenced.

Những gì được sử dụng để quản lý gói Python?

PIP là người quản lý gói thực tế trong thế giới Python.Nó có thể cài đặt các gói từ nhiều nguồn, nhưng PYPI là nguồn gói chính nơi nó được sử dụng.. It can install packages from many sources, but PyPI is the primary package source where it's used.

Cách tốt nhất để quản lý các phụ thuộc trong Python là gì?

Sử dụng VETV và PipENV là hai phương pháp quản lý các phụ thuộc trong Python.Chúng đơn giản để thực hiện và, đối với hầu hết người dùng, các giải pháp đầy đủ để xử lý nhiều dự án với các phụ thuộc khác nhau.Tuy nhiên, chúng không phải là giải pháp duy nhất.Các dịch vụ khác có thể bổ sung cho việc sử dụng của họ.. They are simple to implement and, for most users, adequate solutions for handling multiple projects with different dependencies. However, they are not the only solutions. Other services can complement their use.

Trình quản lý gói nào cho các gói hoặc mô -đun Python?

PIP là người quản lý gói của Python. is python's package manager.