常見問答
常見問答 #
為什麼相依相依決策流程這麼慢?#
雖然 Poetry 核心的相依相依決策程序經過高度最佳化,應該是夠快速處理大部分情況。但在具備特定相依相依設定的情況下,尋找有效方案可能會花點時間。
這是由於並非 PyPI 上的所有函式庫都適切申報了其元資料,因此無法透過 PyPI JSON API 存取。在這個時間點,Poetry 別無選擇,只能下載套件並檢查它們以取得必要的資訊。在頻寬和時間方面,這是一個代價高昂的操作,這也是為何這個程序看似漫長的緣故。
目前沒有解決方式。但是,如果你發現 Poetry 下載了許多個別套件的版本,你可以透過更明確地限制 pyproject.toml 中的套件,來減輕工作負擔。如此一來,Poetry 就不必篩選這麼多版本,在某些情況下可能會顯著加快鎖定程序。
Poetry 使用什麼樣的版本控管機制?#
Poetry 使用「主要版本號.次要版本號.次要修正版本號」版本識別碼,如 PEP 440 中所述。
版本調整操作與 Python 版本調整操作類似
- 主要版本號調整(遞增第一個數字)只會在非相容性變更發生時進行,如果不能採用棄用週期,而多數使用者必須執行一些手動步驟才能從一個版本移轉到下一個版本。
- 次要版本號調整(遞增第二個數字)可能會包含新功能及新棄用事項,並刪除在較早次要版本中已棄用之功能。
- 次要修正版本號調整(遞增第三個數字)通常只包含修正錯誤。已棄用之功能不會在次要修正版本中被刪除。
為何 Poetry 不遵守語意化版本管理? #
由於其大量使用者基礎,即使多數使用者未認為與自己相關的一些微小變更是這些使用者在事後看來卻可能造成非相容性變更。堅持遵守嚴謹的 語意化版本管理,且(幾乎)總是在調整主要版本號而不是次要版本號,似乎不是可取的解決方案,因為次要版本號將不再有意義。
非繫結版本約束是否為不良構想? #
未設定上限的版本約束(例如 *
或 >=3.4
)將允許對相依套件的任何未來版本進行更新。這包括可能破壞向後相容性的主要版本。
在套件的其中一版本已發布後,您將無法再調整其相依套件(相依套件破壞後向相容性時),您必須進行新版本更新,但前一版本仍然破損(使用者仍然可以自行限制受影響相依套件以作為因應解決方法))。
若要避免此類問題,您可以在約束中定義上限,並在測試套件與相依套件的新主要版本相容後,在新的版本中調整上限。
舉例來說,您不使用 >=3.4
而是使用 >3.4
,這將允許所有版本 <4.0
使用 ^
運算子搭配遵循 語意化版本管理 的函式庫非常有效。
然而,當定義上限時,套件使用者即使並未發生任何破損且與套件完全相容時,也無法將相依套件更新為超過上限的版本。您必須先發佈新的套件版本並調整上限。
如果你的套件將會當成其他套件中的函式庫使用,最好避免使用上界,因此減少不必要的相依衝突(除非你已經確定相依套件的下個版本將會讓你的套件失效)。如果你的套件會作為應用程式使用,則可能值得定義上界。
tox 是否受支援?#
是。假設你在使用 tox >= 4,你可以結合 Poetry 提供的 PEP 517 相符建置系統使用它。(在 tox 3 中,你需要設定孤立建置選項。)
因此,在你的 pyproject.toml 檔案中,在不存在的情況下新增這個區段
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
tox
可以使用多種方式設定。這取決於要測試的程式碼和必須安裝哪些相依關係。
使用案例 #1 #
[tox]
[testenv]
deps =
pytest
commands =
pytest tests/ --import-mode importlib
tox
會為專案建立一個 sdist 套件,並使用 pip 在新的環境中安裝它。因此,相依關係是由 pip 解決的。
使用案例 #2 #
[tox]
[testenv]
allowlist_externals = poetry
commands_pre =
poetry install --no-root --sync
commands =
poetry run pytest tests/ --import-mode importlib
tox
會為專案建立一個 sdist 套件,並使用 pip 在新的環境中安裝它。因此,相依關係在第一個地方是由 pip 解決的。但是在那之後,我們執行 Poetry,這將會將鎖定的相依關係安裝到環境中。
使用案例 #3 #
[tox]
[testenv]
skip_install = true
allowlist_externals = poetry
commands_pre =
poetry install
commands =
poetry run pytest tests/ --import-mode importlib
tox
不會執行任何安裝。Poetry 安裝所有相依關係和目前套件處於可編輯模式。因此,測試針對的是本機檔案,而不是已建置和已安裝的套件。
有關認證的注意事項#
請注意tox
預設不會轉發你目前 shell 會話的環境變數。如果在 Linux 系統上使用系統鑰匙串組態認證或使用環境變數,這可能會導致 Poetry 無法在 tox 環境中安裝相依關係。你可以使用 passenv 設定選項 明確轉發必要的變數,或 passenv = "*"
來轉發所有變數。Linux 系統可能需要轉發 DBUS_SESSION_BUS_ADDRESS
變數來允許存取系統鑰匙串,不過這可能會因桌面環境而有所不同。
或者,你可以完全停用鑰匙串
poetry config keyring.enabled false
請注意,這將導致 Poetry 將密碼寫入純文字組態檔案。變更這個設定後,你需要重新設定認證。
Nox 是否受支援?#
使用nox-poetry
套件將 poetry.lock 中指定的相依關係的鎖定版本安裝到 Nox 會話中。
我不希望 Poetry 管理我的虛擬環境。我可以停用它嗎? #
雖然 Poetry 自動建立虛擬環境,以便始終與全域 Python 安裝隔離,但在極少數情況下,使用 Poetry 管理的虛擬環境是不可能或不受歡迎的。
這種情況下,您可以透過將 virtualenvs.create
設定設為 false
來停用此功能
poetry config virtualenvs.create false
建議的最佳實務,包括在容器中安裝應用程式時,是要使用虛擬環境。這也可以由其他工具管理。
Poetry 團隊強烈建議您使用虛擬環境。
為什麼 Poetry 會告訴我目前專案支援的 Python 範圍與一個或多個套件的 Python 需求不相容? #
不像 pip
,Poetry 並非只解析當前環境中的 Python。相反地,它會確保相依關係可以在 pyproject.toml
中指定的 Python 版本範圍內解析。
假設您有下列 pyproject.toml
[tool.poetry.dependencies]
python = "^3.7"
這表示您的專案旨在與任何 Python 版本 >=3.7,<4.0 相容。每當您嘗試新增一個 Python 需求不符合整個範圍的要求時,Poetry 便會告訴您,例如:
The current project's supported Python range (>=3.7.0,<4.0.0) is not compatible with some of the required packages Python requirement:
- scipy requires Python >=3.7,<3.11, so it will not be satisfied for Python >=3.11,<4.0.0
通常您會希望專案支援的 Python 範圍與失敗要求的上限相符。或者,您可以告訴 Poetry 針對特定 Python 版本範圍安裝此相依關係,如果您知道並非所有版本都需要。
為什麼 Poetry 會強制執行 PEP 440 版本? #
這是為了與更廣泛的 Python 生態系統相容。
例如,如果 Poetry 建立一個針對使用未依 PEP 440 規範的版本之專案的套件,第三方工具便無法正確剖析版本。
因為 Poetry 在安裝第三方相依關係之前需要我在複製我的原始檔,所以它會破壞我的 Docker 快取 #
預設情況下,執行 poetry install ...
要求您提供原始檔(「根目錄」套件以及您可能有的任何目錄路徑相依關係)。由於任何原始檔的變更都會讓 Dockerfile 中的所有圖層(後續指令)重新執行,因此這與 Docker 的快取機制互動不佳。例如,您可能有一個類似這樣子的 Dockerfile
FROM python
COPY pyproject.toml poetry.lock .
COPY src/ ./src
RUN pip install poetry && poetry install --only main
只要任何來源檔案變更,RUN
層的快取就會失效,如果您變更了 src/
中的任何檔案,它會強制所有第 3 方依賴關係(可能是這些步驟中花費時間最久的步驟)再次安裝。
為了避免這種快取破壞,您可以將其分成兩個步驟
- 安裝第 3 方依賴關係。
- 複製您的原始碼並僅安裝原始碼。
它可能有點像是這樣
FROM python
COPY pyproject.toml poetry.lock .
RUN pip install poetry && poetry install --only main --no-root --no-directory
COPY src/ ./src
RUN poetry install --only main
我們在此處使用的兩個關鍵選項是 --no-root
(略過安裝專案來源)和 --no-directory
(略過安裝任何本地目錄路徑依賴關係,如果您沒有任何依賴關係,可以省略它)。 瞭解更多關於 poetry install
可用的選項。
我的要求超時了! #
Poetry 的預設 HTTP 要求超時時間為 15 秒,與 pip
相同。類似於 PIP_REQUESTS_TIMEOUT
,可以使用實驗性的環境變數 POETRY_REQUESTS_TIMEOUT
來變更此值。