为什么要换 poetry
对老 Python 来说,pip
看起来是一个不错的选择。我曾经写过一篇使用 conda
或 pip
来对项目依赖进行管理的文章,里面就有一个问题无法解决:在更换了系统/架构之后,可能需要手动编辑依赖列表才能导入。pip
还有一个大的缺陷是无法进行虚拟环境的自动切换。
因此, pip
主要的问题是:
- 没有一个依赖 lockfile(例如
composer.lock
,go.sum
) - 没有自动化的虚拟环境管理
因此,一个比较现代的工具,poetry,闪亮登场。
安装
需要先安装 pipx
,再安装 poetry
。
bash
brew install pipx
pipx ensurepath
pipx install poetry
安装 zsh 自动补全插件
bash
mkdir $ZSH_CUSTOM/plugins/poetry
poetry completions zsh > $ZSH_CUSTOM/plugins/poetry/_poetry
之后需要在 .zshrc
中增加 poetry
插件。
常见用法
在已有项目中初始化 poetry
bash
cd pre-existing-project
poetry init
安装依赖
bash
poetry add <package>
安装全部依赖(已有pyproject.toml
)
bash
poetry install
更新全部依赖
bash
poetry update
配置 pre-commit
首先需要将依赖安装到开发环境中。
- pre-commit: 在 commit 前运行一些脚本
- black: 对代码进行格式化
- isort: 对 import 进行排序
- autoflake: 移除未使用的 import 等
bash
poetry add -G dev pre-commit black isort autoflake
修改 pyproject.toml
。
yaml
[tool.isort]
profile = "black"
增加 .pre-commit-config.yaml
。一定要按照 autoflake -> isort -> black 的顺序执行,不然可能格式化出来的代码又被下一个工具修改成别的样子,导致格式化结果不一致。
值得一提的是,每一步结尾的 git add u
作用是把前面修改的文件重新添加至暂存区(stage),否则后续的工具无法对上一步格式化的文件进行进一步处理。
yaml
fail_fast: true
repos:
- repo: local
hooks:
- id: autoflake
name: Remove unused variables and imports
entry: bash -c 'autoflake "$@"; git add -u' --
language: python
args:
[
"--in-place",
"--remove-all-unused-imports",
"--expand-star-imports",
"--ignore-init-module-imports",
]
- id: isort
name: Sorting import statements
entry: bash -c 'isort "$@"; git add -u' --
language: python
types: [file, python]
- id: black
name: Black Python code formatting
entry: bash -c 'black "$@"; git add -u' --
language: python
types: [file, python]
args: [--line-length=120]
CI/CD 中的使用
见示例 Dockerfile。
第一部分需要为镜像安装 poetry
,然后关闭虚拟环境,全局安装依赖,这一部分其实可以打包成基础镜像。第二部分是项目的依赖安装。第三部分就是将应用代码复制到镜像中(可以用 .dockerignore
来排除部分无用文件来达到减小镜像体积的效果)。
Dockerfile
FROM python:3.11.6-slim
RUN pip install poetry && poetry config virtualenvs.create false
WORKDIR /app
EXPOSE 8000
COPY pyproject.toml poetry.lock ./
RUN poetry install --no-dev
COPY . .
ENTRYPOINT ["python", "main.py"]