為Python專案啟用poetry和pyproject.toml

東方天宇發表於2021-02-06

0. 題引

  • 為什麼要使用poetry?

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

  • 為什麼要使用pyproject.toml?

    首先pytest、black、isort等常用工具都支援pyproject.toml了,可以實現一個檔案完成全專案的配置。
    其次pyproject.toml是PEP中的內容,是將來的方向。試試上,已經有越來越多的開源下專案使用pyproject.toml,我也不能太落後

擴充套件閱讀:

pyproject.toml到底是什麼東西? (freelycode.com)

1. Windows安裝poetry

作為Python的一個第三方庫。擁有統一、便捷的安裝方式:

pip install poetry

但是這樣的安裝方式有一些弊端,因為poetry也依賴了很多的其他的包,這些依賴包會同時的一起安裝進去。那麼這麼多的包,尤其不同版本的包,可能會搗亂我們的Python環境。所以我們需要一個方式來進對他進行隔離。

當然也可以在虛擬環境當中安裝poetry,但是這樣的話有一個弊端,就是可能需要為每一個虛擬環境分別安裝poetry。

所以為了日後使用起來乾淨舒服,在這裡我放棄了這種最便捷的安裝方式,接下來給大家介紹我是如何進行安裝的。

1.1 安裝pipx

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

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

pip install pipx

驗證安裝成功

λ pipx list
venvs are in C:\Users\san\.local\pipx\venvs
apps are exposed on your $PATH at C:\Users\san\.local\bin

1.2 安裝 poetry

C:\Users\san
λ pipx install poetry 
  installed package poetry 1.1.4, Python 3.9.0
  These apps are now globally available
    - poetry.exe
done!

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

C:\Users\san
λ 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
C:\Users\san
λ poetry
Poetry version 1.1.4

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

2. 在專案中使用 poetry

在系統中只有一個poetry就夠了,接下來在各個專案中使用即可。

這裡有一個專案APIPractice, 之前是pip +requirement.txt 半手動的方式管理依賴,接下來改為poetry

2.1 初始化 pyproject.toml

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

C:\Users\san\github\APIPractice>poetry init

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

Package name [apipractice]:
Version [0.1.0]:
Description []:  三木的介面自動化測試練習v1
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 = "三木的介面自動化測試練習v1"
authors = ["dongfangtianyu <7629022+dongfangtianyu@users.noreply.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 = "三木的介面自動化測試練習v1"
authors = []

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

[tool.poetry.dev-dependencies]

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

2.2 建立專案虛擬環境

此時peotry使用的還是pipx為它建立的獨立虛擬環境

C:\Users\san\github\APIPractice>poetry env info

Virtualenv
Python:         3.9.0
Implementation: CPython
Path:           NA

System
Platform: win32
OS:       nt
Python:   c:\users\san\.local\pipx\venvs\poetry

接下來要為專案建立專案虛擬環境,以便安裝專案的各項依賴

C:\Users\san\github\APIPractice>poetry env use python
Creating virtualenv apipractice-gBZexHj9-py3.9 in C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs
Using virtualenv: C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9

所有由poetry建立虛擬環境會會幾種在一個地方,一般情況下,我們不需要直到整個環境的具體路徑,

在專案根目錄執行poetry shell 即可進入整個虛擬環境

C:\Users\san\github\APIPractice>poetry shell
Spawning shell within C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9
Microsoft Windows [版本 10.0.19042.746]
(c) 2020 Microsoft Corporation. 保留所有權利。

C:\Users\san\github\APIPractice>

驗證一下

C:\Users\san\github\APIPractice>pip -V
pip 20.3.3 from C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9\lib\site-packages\pip (python 3.9)

可以在命令列exit, 會從虛擬環境中退出(回到系統級python)

C:\Users\san\github\APIPractice>exit

C:\Users\san\github\APIPractice>pip -V
pip 20.2.3 from c:\users\san\appdata\local\programs\python\python39\lib\site-packages\pip (python 3.9)

2.3 新增新的依賴

既然要使用poetry來進行依賴包的管理,那我們在後面也會的避免使用pip ,

新增依賴的命令

  • poetry add <pakge_name>

但是有些不好用

C:\Users\san\github\APIPractice>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\san\.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沒有使用pip的配置,從其他源下載檔案,所有出現了網路錯誤。

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

解決辦法:

pyproject.toml 檔案中新增如下內容:

[[tool.poetry.source]]
name = "aliyun"
url = "https://mirrors.aliyun.com/pypi/simple"

接下來他會花比較久的時間去分析fastpi的依賴關係,以及依賴包的依賴關係。最終會生成一個大約800行內容的poetry.lock檔案, 並且修改pyproject.toml

[tool.poetry.dependencies]
python = "^3.9"
fastapi = {extras = ["all"], version = "^0.63.0"}

自此,依賴安裝成功。

為了以後避免出現其他的狀況,本專案中儘量不要在用pip做任何事情。。。把pip暫時忘記吧

2.4 新增開發依賴

預設情況下,poetry所新增的依賴是在執行這個專案時所需要的一些包,但是在我們開發的時候,其實還需要一些工具進行配合。

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

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

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

C:\Users\san\github\APIPractice>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是被安裝在虛擬環境當中,所以我們執行拍pytest有兩種方式:

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

    C:\Users\san\github\APIPractice>poetry shell
    Spawning shell within C:\Users\san\AppData\Local\pypoetry\Cache\virtualenvs\apipractice-gBZexHj9-py3.9
    Microsoft Windows [版本 10.0.19042.746]
    (c) 2020 Microsoft Corporation. 保留所有權利。
    
    C:\Users\san\github\APIPractice>pytest
    ==================== test session starts =====================
    platform win32 -- Python 3.9.0, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
    rootdir: C:\Users\san\github\APIPractice
    collected 29 items                                                                                                   
    
    tests\test_default.py ....                   [ 13%]
    tests\test_encrypt.py ...                    [ 24%]
    tests\test_file.py .......                   [ 48%]
    tests\test_login.py ......                   [ 68%]
    tests\test_token.py .........                 [100%]
    
    =============== 29 passed in 1.16s ===============
    
  • 第二種:讓pytest在虛擬環境中執行

    C:\Users\san\github\APIPractice>poetry run pytest
    ==================== test session starts =====================
    platform win32 -- Python 3.9.0, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
    rootdir: C:\Users\san\github\APIPractice
    collected 29 items                                                                                                   
    
    tests\test_default.py ....                   [ 13%]
    tests\test_encrypt.py ...                    [ 24%]
    tests\test_file.py .......                   [ 48%]
    tests\test_login.py ......                   [ 68%]
    tests\test_token.py .........                 [100%]
    
    =============== 29 passed in 1.13s ===============
    

3. 總結

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

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

  1. 初始化pyproject.toml
  2. 建立虛擬環境

之後,主要負責:

  • 管理依賴

  • 切換虛擬環境

使用poetry目前有2個不爽:

  • 依賴分析較慢,安裝包要等待很久
  • 不使用pip配置檔案訪問pypi源,需要指定在pyproject.toml檔案中 (會進入git)

相關文章