python包管理利器-pipx和poerty詳解


1. 題引

1.1 pipx 是什么?

   據官網介紹,pipx 是安裝並運行 Python 終端用戶應用(end-user applications)的工具。
   終端用戶應用,其實可以理解為用 Python 編寫的命令行工具,可以直接從命令行調用的那種。
   有點類似 Mac 下的 brew,類似 JavaScript 的 npx,和 pip 也很像,
只是專門用來安裝命令行工具庫。
   pipx 之所以存在,是因為 Python 和 PyPI 支持開發者發布帶有”終端腳本入口“的代碼,
   用戶可以在命令行調用 Python 代碼,使得這個 Python 包類似於一個獨立的應用。

官網

1.2 pipx 的主要功能

pipx 支持如下功能:

將 Python 包安全地安裝在隔離環境中,同時又可以全局暴露出命令行的調用入口。
這樣可以避免依賴之間的沖突。
列舉、更新和刪除使用 pipx 安裝的包
在臨時環境中運行某個 Python 應用的最新版
pipx 需要 Python 3.6 及以上版本,同時必須已經安裝好了 pip。

1.3 為什么要使用poetry?

因為想使用pyproject.toml,並通過pyproject.toml進行依賴包管理.
目前pip還不支持,所以poetry是首選

1.4 為什么要使用pyproject.toml?

首先pytest、black、isort等常用工具都支持pyproject.toml了,
可以實現一個文件完成全項目的配置。
其次pyproject.toml是PEP中的內容,是將來的方向。
事實上,已經有越來越多的開源下項目使用pyproject.toml,因此我們也有必要學習了解一下

擴展閱讀:

pyproject.toml到底是什么東西?.

2 安裝pipx

pipx會為安裝的每一個包自動創建隔離環境,並自動設置環境變量。
安裝的包能夠被執行,非常使用安裝那些命令行程序,
比如block、httpie、poetry。

首先在系統級python環境中安裝pipx

pip install pipx

將pipx的虛擬環境加入到環境變量里面

pipx ensurepath

按照此命令打印的說明,可以完成shell操作:

pipx completions

驗證安裝成功

pipx list 

如果你尚未安裝任何軟件包,你將看到以下輸出:

  nothing has been installed with pipx ?

2.1安裝 Python 包

以下是 Pipx 入門的一個例子

要全局安裝 Python 應用,例如 cowsay,請運行:

$ pipx install cowsay

此命令將自動創建虛擬環境,在其中安裝包並包的可執行文件放在 $PATH 中。

示例輸出:

installed package cowsay 2.0.3, Python 3.6.8
These binaries are now globally available
- cowsay
done! ✨ ? ✨

讓我們測試新安裝的 cowsay 程序:

$cowsay moon
  ____
| mooo |
  ====
    \
     \
       ^__^
       (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

在這里,它僅僅是一個例子。你可以安裝/測試任何其他的 Python 包。

再次列出pipx 安裝的Python 包

$ pipx list

示例輸出:

venvs are in C:\Users\admin\.local\pipx\venvs
apps are exposed on your $PATH at C:\Users\emijnae\.local\bin
   package cowsay 4.0, Python 3.8.4
    - cowsay.exe

Pipx 的默認虛擬環境位置是 ~/.local/pipx。這可以用環境變量 PIPX_HOME 覆蓋。

   pipx 二進制文件的默認位置是 ~/.local/bin。
   你可以使用 PIPX_BIN_DIR 環境變量覆蓋它。
   如果要覆蓋 PIPX_BIN_DIR,只需運行 userpath append $PIPX_BIN_DIR,
   確保它在你的路徑中。

讓我們繼續看看如何使用 Pipx 安裝 Python 應用。
使用 Pipx 在隔離環境中安裝和運行 Python 應用

2.2升級包

要升級指定的安裝包,只需執行以下操作:

  $ pipx upgrade cowsay

要一次性升級所有已安裝的軟件包,請使用:

  $ pipx upgrade-all

從臨時虛擬環境運行應用

有時,你可能希望運行特定的 Python 程序,但並不實際安裝它。

$ pipx run pycowsay moooo

在臨時隔離虛擬環境中運行 Python 應用

此命令實際上並不安裝指定程序,而是從臨時虛擬環境運行它。你可以使用此命令快速測試 Python 應用。

你甚至可以直接運行 .py 文件。

$ pipx run https://gist.githubusercontent.com/cs01/fa721a17a326e551ede048c5088f9e0f/raw/6bdfbb6e9c1132b1c38fdd2f195d4a24c540c324/pipx-demo.py
pipx is working!

2.3 卸載軟件包

可以使用以下命令卸載軟件包:

$ pipx uninstall cowsay

要刪除所有已安裝的包:

$ pipx uninstall-all

2.4 獲得幫助

要查看幫助部分,請運行:

$ pipx --help

就是這些了。如果你一直在尋找安全,方便和可靠的程序來安裝和運行 Python 應用,Pipx 可能是一個不錯的選擇。

資源:Pipx 的 GitHub 倉庫

3 安裝 配置poetry

3.1 安裝

可以使用python自帶的pip工具來安裝,但是這里我們使用pipx來安裝

  pipx install poetry 
  installed package poetry 1.1.4, Python 3.9.0
  These apps are now globally available
    - poetry.exe
done!

安裝成功后,使用pipx檢查安裝效果

pipx list
venvs are in C:\Users\san\.local\pipx\venvs
apps are exposed on your $PATH at C:\Users\san\.local\bin
   package poetry 1.1.4, Python 3.9.0
    - poetry.exe

檢查一下是否安裝成功

poetry
Poetry version 1.1.10

USAGE
  poetry [-h] [-q] [-v [<...>]] [-V] [--ansi] [--no-ansi] [-n] <command> [<arg1>] ... [<argN>]

ARGUMENTS
  <command>              The command to execute
  <arg>                  The arguments of the command

GLOBAL OPTIONS
  -h (--help)            Display this help message
  .......

自此,poetry就已經安裝好了。

我們是通過pipx安裝的poetry,日后也可以通過pipx 更新poetry:

pipx upgrade poetry

3.2配置設置

查詢當前所有配置

$ poetry config list
cache-dir = "/home/$user/.cache/pypoetry"
experimental.new-installer = true
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/$user/.cache/pypoetry/virtualenvs

查詢單個配置

poetry config virtualenvs.path 

添加或者更新配置

poetry config virtualenvs.in-project true 

刪除配置

poetry config virtualenvs.path --unset 

查看可用軟件包

根據 poetry.lock 列出所有可用的軟件包,並不是根據 pyproject.toml 文件的 [tool.poetry.dependencies]

poetry show

查看某個包的詳細信息

$ poetry show fastapi 
name         : fastapi
version      : 0.61.2
description  : FastAPI framework, high performance, easy to learn, fast to code, ready for production

dependencies
 - pydantic >=1.0.0,<2.0.0
 - starlette 0.13.6

options

--no-dev:不要列出開發依賴項

--tree:樹的形式列出依賴項

--latest (-l):顯示最新版本
--outdated (-o):顯示最新版本,但僅適用於過時的軟件包

4. 在項目中使用 poetry

4.1新建項目

new

通過創建適合大多數項目的目錄結構來啟動新的Python項目

poetry new my-package 

my-package 是路徑,默認目錄結構:

 my-package
    ├── pyproject.toml              # poetry 用於管理項目的 all-in-one 配置文檔.
    ├── README.rst                  # 說明文檔
       ├── my_package               # poetry 會幫你將包名調整為下划線格式.
    │   └── __init__.py             # 請在該目錄下編寫你的業務邏輯.
    └── tests                       # 測試模塊.
        ├── __init__.py               
        └── test_my_package.py

它有如下參數:

	OPTIONS
	  --name           Set the resulting package name.自定義項目名稱
      --src            Use the src layout for the project.  使用 src 目錄

比如創建一個名字為my-folder的項目,並使用src目錄:

poetry new my-folder --name my-package  --src

目錄結構

my-folder
├── pyproject.toml
├── README.rst
├── src
│   └── my_package
│       └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py

4.2初始化一個項目

poetry init

如果想在已存在的 Python 項目使用 poetry,可以用 init 命令,poetry 會以交互方式創建 pyproject.toml 文件

在項目的根目錄,執行poetry是, 並一路回車

poetry init
This command will guide you through creating your pyproject.toml config.

Package name [apipractice]:
Version [0.1.0]:
Description []: 
Author []:
License []:
Compatible Python versions [^3.9]:

Would you like to define your main dependencies interactively? (yes/no) [yes]
You can specify a package in the following forms:
  - A single name (requests)
  - A name and a constraint (requests@^2.23.0)
  - A git url (git+https://github.com/python-poetry/poetry.git)
  - A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
  - A file path (../my-package/my-package.whl)
  - A directory (../my-package/)
  - A url (https://example.com/packages/my-package-0.1.0.tar.gz)

Search for package to add (or leave blank to continue):

Would you like to define your development dependencies interactively? (yes/no) [yes]
Search for package to add (or leave blank to continue):

Generated file
[tool.poetry]
name = "apipractice"
version = "0.1.0"
description = ""
authors = ["$user <email@github.com>"] 

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

Do you confirm generation? (yes/no) [yes]

在Do you confirm generation? (yes/no) [yes] 后按下回車之后,將會在當前目錄生成pyproject.toml,內容如下


[tool.poetry]
name = "apipractice"    # 項目名稱,默認會填寫當前目錄的名稱
version = "0.1.0"       # 默認版本
description = ""        # 對本項目簡單的描述
authors = ["$user <email@github.com>"]  

[tool.poetry.dependencies]
python = "^3.9"       # 版本依賴包括python版本和第三方庫

[tool.poetry.dev-dependencies]  # 開發模式下依賴的第三方庫

[build-system]  # 默認構建項目時使用的內容,一般不用改
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

我是一只回車沒有自己輸入東西的
options

--name:包的名稱
--description:包的描述
--author:包的作者
--python:兼容的 Python 版本
--dependency:需要具有版本約束的包,格式 foo:1.0.0
--dev-dependency:開發需求

生成 pyproject 已有的字段 和 options 是可以對齊的

4.3 安裝依賴

從當前項目讀取 pyproject.toml 文件,解析依賴項 [tool.poetry.dependencies] 並安裝它們

poetry install

如果當前目錄中有 poetry.lock 文件,它將使用其中的確切版本,而不是解析它們, 這確保使用庫的每個人都將獲得相同版本的依賴項
如果沒有 poetry.lock 文件,poetry 將在依賴項解析后創建一個

重點

默認會安裝 [tool.poetry.dependencies] 和 [tool.poetry.dev-dependencies] 下所有強制安裝的(不帶 optional)依賴項
它有如下參數

--no-dev    	不安裝開發依賴項 [tool.poetry.dev-dependencies] 

poetry install --no-dev

--remove-untracked	移除 poetry.lock 文件中不再存在的舊依賴項

poetry install --remove-untracked

-E|--extras	指定安裝的包

poetry install --extras

--no-root	不要安裝根目錄包

poetry install  	--no-root	

同時,記得上面提到的這個參數

poetry config virtualenvs.in-project true

如果沒有設置,可以配置一下,但是最好的方法是在項目目錄下創建一個文件poetry.toml,寫下如下內容:

[virtualenvs]
in-project = true

這樣能夠保證,在使用poetry安裝依賴文件時自動創建虛擬環境。
然后使用的時候執行下面命令激活虛擬環境

source .venv/bin/activate

4.4 其他命令

update

獲取所有依賴項的最新版本並更新 poetry.lock 文件

poetry update

指定依賴項進行更新

poetry update requests toml

options

--dry-run :輸出操作,但不執行操作
--no-dev : 不安裝開發依賴項
--lock:不執行安裝,僅更新 poetry.lock 文件

add

將所需要的包添加到 pyproject.toml 的 [tool.poetry.dependencies] 下面,並安裝他們
未指定版本的話,則 poetry 會自動選擇合適的版本

poetry add requests pendulum

注意

默認不會將包添加到 [tool.poetry.dev-dependencies] 下,若需要得用 --dev 參數
指定版本

poetry add pendulum@^2.0.5
poetry add "pendulum>=2.0.5"

獲取最新的版本

poetry add pendulum@latest

添加 github 依賴項

poetry add git+https://github.com/sdispater/pendulum.git

添加 github 依賴項,指定分支

poetry add git+https://github.com/sdispater/pendulum.git#develop
poetry add git+https://github.com/sdispater/pendulum.git#2.0.5

通過本地目錄、文件進行安裝

poetry add ./my-package/
poetry add ../my-package/dist/my-package-0.1.0.tar.gz
poetry add ../my-package/dist/my_package-0.1.0.whl

以可編輯模式安裝依賴項

在 pyproject.toml 文件指定,意味着本地目錄中的更改會直接反映在環境中

[tool.poetry.dependencies]
my-package = {path = "../my/path", develop = true}

options

--dev (-D):將包添加為開發依賴項
--path:指定依賴項的路徑
--optional:作為可選依賴項添加
--dry-run:輸出操作,不執行任何操作
--lock:不執行安裝,僅更新 poetry.lock 文件

remove

從已安裝包列表刪除指定包

poetry remove pendulum
options

    --dev(-D):從開發依賴項中刪除包
    --dry-run:輸出操作,不執行任何操作

show

根據 poetry.lock 列出所有可用的軟件包,並不是根據 pyproject.toml 文件的 [tool.poetry.dependencies]

poetry show

查看某個包的詳細信息

poetry show fastapi  

options

--no-dev:不要列出開發依賴項

--tree:樹的形式列出依賴項

--latest (-l):顯示最新版本
--outdated (-o):顯示最新版本,但僅適用於過時的軟件包

run

在項目的 virtualenv 中執行指定的命令

poetry run python -V

還可以執行 pyproject.toml 中定義的腳本

[tool.poetry.scripts]
my_script = "my_module:main"

執行 shell

poetry run my_script

顯式激活當前虛擬環境,會自動調用虛擬環境下的激活命令

如果不存在虛擬環境,會自動創建一個

check

驗證 pyproject.toml 文件的結構,並在出現任何錯誤時返回詳細報告

poetry check

在遠程庫上搜索包

poetry search requests

lock

將所有依賴項鎖定為最新的可用兼容版本

poetry lock

version

顯示項目的當前版本

是 pyproject.toml 文件的 version 哦

export

將鎖文件導出為其他格式

poetry export -f requirements.txt --output requirements.txt

options

--format (-f):要導出的格式(默認值:requirements.txt)目前,僅支持requirements.txt
--output (-o):輸出文件的名稱,如果省略,則打印到標准輸出
--dev(-D):從開發依賴項中刪除包
--extras (-E):要包含的額外依賴項集
--without-hashes:從導出的文件中排除散列
--with-credentials:包括用於額外索引的憑據

env

管理虛擬環境,具體教程看:https://www.cnblogs.com/poloyy/p/15270670.html
cache

build

生成源文件

poetry build

publish

將使用 build 命令生成的包發布到遠程存儲庫

poetry publish

options

--repository (-r):要將包注冊到的存儲庫(默認值:pypi)應與config命令設置的存儲庫名稱匹配
--username (-u):訪問存儲庫的用戶名
--password (-p):訪問存儲庫的密碼
--dry-run:執行除上傳包以外的所有操作

5 使用過程中遇到的問題

5.1 依賴源的問題

添加依賴的命令

poetry add <pakge_name>

但是有些不好用

poetry add fastapi[all]
Using version ^0.63.0 for fastapi

Updating dependencies
Resolving dependencies...

  ConnectionError

  HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/f4/2b/078a9771ae4b67e36b0c2a973df845260833a4eb088b81c84b738509b4c4/aiofiles-0.5.0-py3-none-any.whl (Caused by NewConnectionError('
<urllib3.connection.HTTPSConnection object at 0x0000021BE6355250>: Failed to establish a new connection: [WinError 10060] 由於連接方在一段時間后沒有正確答復或連接的主機沒有反應,連接嘗試失敗。'))

  at c:\users\admin\.local\pipx\venvs\poetry\lib\site-packages\requests\adapters.py:516 in send
      512│             if isinstance(e.reason, _SSLError):
      513│                 # This branch is for urllib3 v1.22 and later.
      514│                 raise SSLError(e, request=request)
      515│
    → 516│             raise ConnectionError(e, request=request)
      517│
      518│         except ClosedPoolError as e:
      519│             raise ConnectionError(e, request=request)
      520│

從錯誤提示來看,從其他源下載文件,所以出現了網絡錯誤。

這是poetry已經被吐槽很多次的問題了。。。

解決辦法:

pyproject.toml 文件中添加清華鏡像或者阿里雲鏡像:

[[tool.poetry.source]]
name = "aliyun"
url = "https://mirrors.aliyun.com/pypi/simple"
# name = "tsinghua"
# url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/"

但是這不能夠完全保證,依然會遇到一些問題
[[tool.poetry.source]] 僅對部分環節有效, 在某些步驟 (如 resolve dependencies...) poetry 仍然使用的是 pypi url,
而我們國內訪問不了或者連接超時, 就引起了報錯.

解決方法:

加一個 default 參數:

[[tool.poetry.source]]
name = "tsinghua"
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/"
default = true  # 添加一個 default 參數, 使 poetry 的默認回調行為都調用到這個清華鏡像上.

參考:

https://github.com/python-poetry/poetry/issues/559
https://python-poetry.org/docs/repositories/#disabling-the-pypi-repository

5.2 添加開發依賴

默認情況下,poetry所添加的依賴是在運行這個項目時所需要的一些包,但是在我們開發的時候,其實還需要一些工具進行配合。

比如說測試框架pytest,如果單純是為了啟動這個項目的話,其實是不需要進行安裝的。

所以把這些在運行時不需要安裝,在開發時所需要安裝的依賴我們稱之為開發依賴。

安裝開發依賴的方式很簡單,就是加一個-D參數

poetry add -D pytest
Using version ^6.2.2 for pytest

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 9 installs, 0 updates, 0 removals

  • Installing pyparsing (2.4.7)
  • Installing atomicwrites (1.4.0)
  • Installing attrs (20.3.0)
  • Installing iniconfig (1.1.1)
  • Installing packaging (20.9)
  • Installing py (1.10.0)
  • Installing pluggy (0.13.1)
  • Installing toml (0.10.2)
  • Installing pytest (6.2.2)

然后我們運行pytest執行測試。

有兩種方式來驗證:

第一種:先進入虛擬環境,然后執行pytest

poetry shell
pytest

第二種:讓pytest在虛擬環境中執行

poetry run pytest
   
=============== 29 passed in 1.13s ===============

5.3 什么時候使用 ‘poetry.lock’, 什么時候不使用?

多數人以及要發布模塊到 pypi 的人不需要 poetry.lock; 通過 Version Control 進行協作的開發團隊以及對他機部署環境要求非常嚴格的人則需要放入 poetry.lock.

poetry.lock 的意義在於, 它會徹底 “鎖死” 項目依賴的版本,

比如我們在 pyproject.toml 中要求的依賴版本是 requests = "^2.24.0",

那么哪怕 requests 的作者后面發布了 2.24.1, 使用 poetry.lock 安裝時仍會選擇安裝 2.24.0 版本.

因此, poetry.lock 幫助我們徹底杜絕因依賴的版本的微小變化而產生的任何不確定性.

補充說明:

如需使用 poetry.lock, 請將它伴隨項目一起打包發布, 在執行 poetry install 時它會優先查找 lock 文件.

你可以通過 poetry update 來更新所有依賴到最新版本, 同時 poetry.lock 也會鎖定到新的依賴版本.

當pyproject.toml 中所列的依賴與 poetry.lock 不匹配時, poetry install 會中斷並提示該錯誤.

5.4 為項目添加執行入口

我們可以將項目啟動的命令,或者啟動入口寫為腳本,然后加入到配置文件中,然后文件執行 poetry install 操作時,就會將項目編譯為可執行文件了

[tool.poetry.scripts]
  package-transformer = "newapi.test:main"

這里注意格式, “ package-transformer”是編譯生成的可執行目標文件,方便以后運行使用
"newapi.test:main" 是程序執行的如可文件和函數名

6 例子和總結

現在新的項目已經使用poetry和pyproject.toml來進行管理了。

poetry new  newtest --name newapi
[tool.poetry]
name = "newapi"
version = "0.1.0"
description = ""
authors = ["Dummy"]

[tool.poetry.dependencies]
python = "^3.8"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

# 程序執行入口
[tool.poetry.scripts]
  test-package = "newapi.main:main"

# 添加清華源,防止構建依賴時因為網絡問題不能構建成功
[[tool.poetry.source]]
name = "tsinghua"
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/"
default = true  # 添加一個 default 參數, 使 poetry 的默認回調行為都調用到

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

main文件:

import time
import os

def test():
   print('hello word')
   print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))

def main(**kwargs):
   """Entry point """
   test()
   print(os.getcwd())
   time.sleep(10)
   print('test end after 10s')

if __name__ == "__main__":
    main()

現在項目結構如下:‘

 newtest
    ├── pyproject.toml              # poetry 用於管理項目的 all-in-one 配置文檔.
    ├── README.rst                  # 說明文檔
       ├── newapi               # poetry 會幫你將包名調整為下划線格式.
    │    ├──__init__.py             # 請在該目錄下編寫你的業務邏輯.
    │   └── main.py              
    └── tests                       # 測試模塊.
        ├── __init__.py               
        └── test_my_package.py

夠構建環境`

poetry install

激活虛擬環境

source .venv/Script/activate

根據構建的程序入口運行程序

test-package

回顧發現,poetry在開始做了幾件件事:

初始化pyproject.toml
構建主程序入口
修改配置文件,增加程序入口和修改鏡像源
創建虛擬環境
構建下載相關依賴
根據配置信息生成可執行入口

之后,主要負責:

管理依賴


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM