Python Note 01
套件、虛擬環境管理工具-Poetry
使用Python來開發軟體時,管理在專案中使用的套件和Python版本是一件麻煩的事情,從一開始接觸的pip install
、或是管理不同專案的虛擬環境conda
來安裝不同版本的Python或是套件,都或多或少會有一些相依性的問題。
尤其是使用pip uninstall
的時候,解除安裝套件時就只會解除安裝你指定的套件,其他相依的套件通常都不會被一併解除安裝,這就會遇到一些關於相依性的問題,餘下的套件可能會和之後新安裝的套件產生衝突,所以我們需要一個完整的套件相依性管理工具來處理這個問題,而Poetry
就是負責管理套件相依性、依賴性和虛擬環境的工具。
poetry
具體的指令或方法建議參考官方網站的指令,
安裝Poetry
安裝poetry
在Windows需要使用Powershell來安裝,打開Powershell輸入以下指令(目前安裝的版本為1.6.1) :
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
如果是linux、macOS或是Windows的WSL則是用以下指令,如果需要安裝python2的poetry指令內的python3可以更改為python2:
curl -sSL https://install.python-poetry.org | python3 -
如果安裝時遇到:
Poetry installation failed.
See /home/username/poetry-installer-error-4khp4juv.log for error logs.
去看log會發現缺少distutils
,這是用於協助建立和分發Python套件的工具:
ModuleNotFoundError: No module named 'distutils.cmd'
需要你安裝python3-distutils
,用以下指令安裝:
sudo apt-get install python3-distutils
如果是Windows安裝完的位置會在%APPDATA%\Python\Scripts
而Unix系統則是在$HOME/.local/bin
上,如果要直接使用要設定環境變數PATH,Windows直接使用以下指令或是前往環境變數設定的地方新增即可,其中的使用者要記得改為自己的使用者名稱:
$Env:Path += ";C:\Users\YourUserName\AppData\Roaming\Python\Scripts"; setx PATH "$Env:Path"
Unix系統則是要在.zshrc
、.bashrc
或.bash_profile
新增以下的指令:
export PATH=$PATH:$HOME/.local/bin
安裝完後會發現如果按下TAB
是無法補全剩餘的字串的,如果是在Unix下使用bash,加上以下這段可以恢復補全功能:
poetry completions bash >> ~/.bash_completion
初始化Poetry專案
使用Poetry的話需要在你使用Poetry的資料夾使用以下指令,會跳出一連串的互動對話協助建立專案,其中會問你是否要以互動方式定義你的main/development依賴這兩個問題,這兩個我都選no,而最後會print出你的設定檔內容要你確認:
poetry init
結束後會新增一個pyproject.toml
做為設定檔:
[tool.poetry]
name = "your_project_name"
version = "0.1.0"
description = ""
authors = ["AuthorName <your@email.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10.11"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
除了使用init
外,還可以用new的方式建立專案,除了會建立pyproject.toml
以外還會建構一些資料夾或檔案,後面可以接上你專案名稱將專案資料夾建立在你目前的位置上,或是加上路徑建立在你指定的資料夾內:
poetry new your_project
poetry new your_project_path
建立/進入Python虛擬環境
Poetry預設建立虛擬環境的位置在C:\Users\YourUserName\AppData\Local\pypoetry\Cache\virtualenvs
,可以透過設定將建立虛擬環境的路徑改在專案下,首先使用以下指令列出poetry的設定:
poetry config --list
在Windows的設定內容如下,其中要修改virtualenvs.in-project = null
,讓虛擬環境的路徑改為你專案目錄:
cache-dir = "C:\\Users\\YourUserName\\AppData\\Local\\pypoetry\\Cache"
experimental.system-git-client = false
installer.max-workers = null
installer.modern-installation = true
installer.no-binary = null
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}\\virtualenvs" # C:\Users\YourUserName\AppData\Local\pypoetry\Cache\virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"
使用以下指令就可以更改設定:
poetry config virtualenvs.in-project true
用以下指令建立虛擬環境,其中python可以改為你要使用的python路徑,因為已經將虛擬環境建立的路徑改為專案內,所以在專案內會建立.venv
的資料夾,也就是你的python虛擬環境:
poetry env use python
可以在Windows使用where指令或在Linux使用which找到你的python安裝路徑:
where python
which python3
建立虛擬環境後,可以使用poetry shell
進入虛擬環境:
poetry shell
指令會偵測當前的目錄或上一層目錄是否存在pyporject.toml
來確定要啟動的虛擬環境,如果沒有會出現以下錯誤:
> poetry shell
Poetry could not find a pyproject.toml file in /currnet/path or its parents
退出跟一般進入環境的方式一樣,使用exit
即可。
Poetry常用指令
Poetry在使用的時候跟Anaconda
很像,都是透過自己的指令來建立、管理你的python虛擬環境,比起Anaconda
或是PyPI
他使用的方式複雜了一些,需要花費一些時間來學習。
poetry add
poetry add
跟pip install
或conda install
一樣是用來安裝套件的,這裡示範安裝pandas
,可以清楚地看到安裝了哪一些套件:
poetry add pandas
Using version ^2.1.0 for pandas
Updating dependencies
Resolving dependencies...
Writing lock file
Package operations: 5 installs, 0 updates, 0 removals
• Installing six (1.16.0)
• Installing python-dateutil (2.8.2)
• Installing pytz (2023.3.post1)
• Installing tzdata (2023.3)
• Installing pandas (2.1.0)
打開pyproject.toml
會發現在tool.poetry.dependencies
多了pandas
和它對應的版本號:
[tool.poetry.dependencies]
python = "3.10.10"
pandas = "^2.1.0"
poetry lock
poetry add
除了會更新pyproject.toml
以外,還會根據目前專案中pyproject.toml
內的設定產生poetry.lock
檔案,詳細記載了所有安裝的套件與對應的版本、依賴的套件。
所以大體上Poetry管理套件的流程是:
- 更新
pyproject.toml
- 依照
pyproject.toml
內的設定更新poetry.lock
- 根據
poetry.lock
創建對應的虛擬環境.venv
所以說Poetry中的指令只要有涉及到對套件進行更改的部分,都是會按照這個流程去進行,如果不使用指令操作直接對pyproject.toml
進行更改,譬如調整特定套件的版本,這時候pyproject.toml
和poetry.lock
之間就失去了對應的關係,需要透過poetry lock
這指令讓Poetry依照pyproject.toml
內的設定,來更新poetry.lock
。
譬如我更改了之前安裝的pandas
套件版本,^
的意思是任何大於或等於 2.1.0 且小於 3.0.0的版本,所以改為 (不加上^
) 2.0.0 :
[tool.poetry.dependencies]
python = "3.10.10"
pandas = "2.0.0" # 原為^2.1.0
使用poetry lock
來更新poetry.lock
檔案:
> poetry lock
Updating dependencies
Resolving dependencies...
Writing lock file
在poetry.lock
上會看到更新後對應的版本:
# 前略
[[package]]
name = "pandas"
version = "2.0.0"
# 後略
接下來還有最後一步驟,就是把poetry.lock
的更改寫入對應虛擬環境:
poetry install --sync
- 如果當前目錄中有
poetry.lock
文件,poetry install
會使用那裡的確切版本。 - 如果沒有
poetry.lock
,會從當前專案中讀取pyproject.toml
文件,解析依賴項並安裝它們。
poetry update
poetry update
的作用就是更新套件,可以直接使用指令更新目前所有有用到的套件,也可以針對特定的套件進行更新:
poetry update
poetry update pandas
除此之外poetry update
的實現流程和上一部分介紹的poetry lock
流程是一樣的,poetry update
同樣也會根據pyproject.toml
來產生對應的poetry.lock
,不過會把後續的poetry install
也一併執行。
將pandas
版本改回^2.1.0,並執行poetry update
:
[tool.poetry.dependencies]
python = "3.10.10"
pandas = "^2.1.0"
會得到以下結果:
Updating dependencies
Resolving dependencies...
Package operations: 0 installs, 1 update, 0 removals
• Updating pandas (2.0.0 -> 2.1.0)
Writing lock file
更新poetry.lock
的同時也會套用到虛擬環境:
>>> import pandas as pd
>>> pd.__version__
'2.1.0'
poetry show
poetry show
的作用跟pip list
、conda list
一樣,都是列出所安裝的套件,直接使用的結果如下:
numpy 1.25.2 Fundamental package for array computing in Python
pandas 2.1.0 Powerful data structures for data analysis, time series, and stat...
python-dateutil 2.8.2 Extensions to the standard Python datetime module
pytz 2023.3.post1 World timezone definitions, modern and historical
six 1.16.0 Python 2 and 3 compatibility utilities
tzdata 2023.3 Provider of IANA time zone data
除此之外還有一個特別的功能,就是列出套件的樹狀結構,使用方法是直接在poetry show
後面加上--tree
參數,用這種方式可以顯示主要套件和依賴套件的關係與階級,結果如下:
pandas 2.1.0 Powerful data structures for data analysis, time series, and statistics
├── numpy >=1.22.4
├── numpy >=1.23.2
├── python-dateutil >=2.8.2
│ └── six >=1.5
├── pytz >=2020.1
└── tzdata >=2022.1
也可以列出指定的套件,如下:
poetry show pandas
poetry show pandas --tree
poetry remove
poetry remove
的作用如同字面上一樣是用來移除不要的套件,在指令後面要加上要移除的套件名稱:
poetry remove pandas
從輸出結果可以看到除了把pandas移除以外,也將依賴的套件一併移除了:
Updating dependencies
Resolving dependencies...
Package operations: 0 installs, 0 updates, 6 removals
• Removing numpy (1.25.2)
• Removing pandas (2.0.0)
• Removing python-dateutil (2.8.2)
• Removing pytz (2023.3.post1)
• Removing six (1.16.0)
• Removing tzdata (2023.3)
Writing lock file
group
在python有一些套件可能只會在開發的時候用到,像是code formatter相關的套件black
、yapf
,或是負責測試的套件pytest
,這些都只會在開發的時候使用到,你不會希望被包在部署環境裡面,無謂的增加大小使得部署環境過於臃腫。
所以在安裝套件的時候可以加上--group
或是-G
來區分開發環境或是測試環境所需安裝的套件,預設主環境的group名稱是目前新的版本改成用group來區分,預設的主環境為main
tool.poetry.dependencies
:
poetry add black --group dev
poetry add pytest --group test
poetry add pandas --group main
如果是第一次加上group
來安裝套件,打開pyproject.toml
會發現除了tool.poetry.dependencies
以外多了一段,這是在group
環境中所需要安裝套件,如下:
[tool.poetry.group.yourgroupname.dependencies]
package_name = "^version"
前面在介紹把poetry.lock
的更改寫入對應虛擬環境會用poetry install
這個指令,在還沒有建立虛擬環境的時候,要安裝不同的group
的話,可以在後面添加--without
、--with
或--only
;如果已經建立虛擬環境的時候,可以透過--sync
選項同步環境並確保與poetry.lock
匹配 :
# 排除test和docs group
poetry install --without test,docs
# 選擇test group
poetry install --with test
# 僅安裝test group
poetry install --only test
# sync 一樣可以套用with、without、only
poetry install --without test --sync
poetry install --with test --sync
poetry install --only test --sync
如果想將環境還原成沒有安裝套件的狀態,可以透過以下指令,環境就只會剩下python本身的基礎套件:
poetry install --only-root --sync
具體的指令可以參考官方文件的說明。
poetry export
雖然說已經使用Poetry來管理python套件,但還是有可能會需要轉到其他沒有Poetry的環境使用,那就需要將安裝的套件匯出成requirements.txt
,再到其他環境用pip install
來安裝,這時候就需要poetry export
:
poetry export -f requirements.txt -o requirements.txt
如果要指定輸出的group
和前面的poetry install
一樣,要使用--with
、--without
或是--only
來指定要使用的group
,規則和前面介紹的一樣:
poetry export -f requirements.txt -o requirements.txt --only test,docs
輸出的requirements.txt
預設會有hash值,用pip install
安裝會檢查這些hash:
pandas==2.1.0 ; python_full_version >= "3.10.11" and python_full_version < "4.0.0" \
--hash=sha256:0164b85937707ec7f70b34a6c3a578dbf0f50787f910f21ca3b26a7fd3363437 \
# 下略
如果不要有hash,加上--without-hashes
就行:
poetry export -f requirements.txt -o requirements.txt --without-hashes
如果要在Docker上使用Poetry來安裝專案內使用的套件,有一篇文章詳細的介紹如何用Docker透過Poetry安裝套件且產生最小化的Image。
總結常用指令
poetry init
/poetry new <專案路徑>
: 初始化專案poetry env use <python路徑>
: 建立環境用poetry shell
: 進入建立的虛擬環境poetry add
: 安裝套件poetry lock
: 根據pyproject.toml
更新poetry .lock
poetry install
: 根據poetry.lock
更新虛擬環境poetry update
: 更新套件poetry show
: 列出安裝的套件poetry remove <套件名稱>
: 移除指定套件poetry export
:匯出安裝的套件