推荐使用:pyenv 管理版本 + poetry 管理依赖
pyenv 可让您轻松地在多个 Python 版本之间切换。
推荐使用:pyenv 管理版本 + poetry 管理依赖
https://github.com/pyenv/pyenv
https://github.com/pyenv/pyenv/wiki
https://github.com/pyenv/pyenv/wiki/Plugins
# 安装环境依赖以供pyenv编译安装python时使用
$ brew install openssl readline sqlite3 xz zlib tcl-tk
# 安装pyenv
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
# 为 Pyenv 设置 shell 环境
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
# 重新加载 Shell 配置文件并将更改应用于当前会话
$ exec "$SHELL"
# 查看pyenv版本
$ pyenv -v
当您执行 shim 时,pyenv 通过按以下顺序从以下源读取来确定要使用的 Python 版本:
PYENV_VERSION
变量(如果指定)。您可以使用该pyenv shell
命令在当前 shell 会话中设置此环境变量。.python-version
当前目录中的应用程序特定文件(如果存在)。.python-version
您可以使用命令修改当前目录的 文件pyenv local
。.python-version
文件(如果有),直到到达文件系统的根目录。$(pyenv root)/version
文件。您可以使用pyenv global
命令修改此文件。如果全局版本文件不存在,pyenv 假设您想要使用“系统”Python(见下文)。# 查看 pyenv 的版本
$ pyenv -v
# 查看当前使用版本
$ pyenv version
# 罗列当前已安装的所有 python 环境,如果是当前正在使用的环境,则前面会有个 *
$ pyenv versions
# 查看帮助
$ pyenv help
# 如果输入 pyenv 之后使用 tab 不补全,可以使用该命令进行初始即可使用补全命令
$ pyenv init
# 列出所有可安装的Python 版本
$ pyenv install -l
# 安装CPython 3.9.17
# pyenv 会尽力下载并编译想要的 Python 版本
$ pyenv install 3.9.17
# 安装 CPython 3.9.17 并为编译过程传递优化参数以获得最佳性能
$ env PYTHON_CONFIGURE_OPTS='--enable-optimizations --with-lto' PYTHON_CFLAGS='-march=native -mtune=native' pyenv install 3.9.17
# 仅选择当前 shell 会话,临时生效,优先级高于 global
$ pyenv shell <version>
# 会在当前目录创建 .python-version 文件,并记录设置的 python 环境,每次进入该目录会自动设置成该 python 环境
$ pyenv local <version>
# 为您的用户帐户全局选择,重启不会造成再次更改
$ pyenv global <version>
$ pyenv uninstall <versions>
$ rm -rf ~/.pyenv
# 最后在~/.bash_profile中删除相关配置即可
我们不要安装pyenv-virtualenv,而是应该使用Poetry进行虚拟环境的管理,这样可以做到思路清晰,而Poetry的虚拟环境更加的方便好用。
再次强调:有了 Poetry,就不要再装pyenv-virtualenv了。
Poetry 是一个Python 中的好用的包管理工具。在 Python 中,打包系统和依赖管理非常复杂:一个项目经常要同时创建多个文件,例如:
setup.py
requirements.txt
setup.cfg
MANIFEST.in
Pipfile
基于此, poetry 将所有的配置都放置在一个 toml 文件中,包括:依赖管理、构建、打包、发布等,可谓是简单方便。
Poetry用一个简单的基于pyproject.toml
的项目格式取代了setup.py
、requirements.txt
、setup.cfg
、MANIFEST.in
和Pipfile
。
pyproject.toml
:这是一个配置文件,它用于定义项目的元数据和依赖关系。在pyproject.toml文件中,您可以指定项目的名称、版本、作者等信息,并列出项目所需的依赖项及其版本范围。该文件还可以包含构建和发布项目的相关配置。
poetry.lock
:这是一个生成的锁定文件,它记录了确切的依赖关系版本。当运行poetry install
命令时,Poetry会解析pyproject.toml文件并生成poetry.lock
文件。锁定文件中列出了每个依赖项及其确切的版本号。这确保了在不同的开发环境或部署环境中都使用相同的依赖版本,从而增加项目的可重现性和稳定性。
实际上就相当于pip 的requirements.txt
,详细记载了所有安装的包与版本。
区别:pyproject.toml是用于定义项目的元数据和依赖关系的配置文件,而poetry.lock是根据pyproject.toml文件生成的锁定文件,记录了确切的依赖版本。
pyproject.toml提供了依赖范围(例如,指定一个范围的最小和最大版本),而poetry.lock提供了精确的版本号。
作为应用程序开发人员:您应该将该poetry.lock
文件提交到您的项目存储库,以便所有从事该项目的人员都被锁定到相同版本的依赖项。
作为库开发人员:库开发人员需要考虑更多。您的用户是应用程序开发人员,您的库将在您无法控制的 Python 环境中运行。您应该省略poetry.lock
文件。
https://python-poetry.org/docs/#installing-with-the-official-installer
Poetry的安装需要 Python 环境来运行,因为默认会采用Python虚拟环境的方式安装Poetry。
# 确认python环境
$ python -V
# 使用官方安装脚本进行安装
$ curl -sSL --insecure https://install.python-poetry.org | python3 -
# 添加Poetry可执行文件目录到环境变量中
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bash_profile
# 重新加载 Shell 配置文件并将更改应用于当前会话
$ exec "$SHELL"
# 查看poetry版本
$ poetry --version
# 为Zsh 启用 poetry 命令的 Tab 键补全功能 或查看poetry help completions
$ mkdir ~/.zfunc
$ poetry completions zsh > ~/.zfunc/_poetry
$ echo 'fpath+=~/.zfunc' >> ~/.zshrc
$ echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
$ exec "$SHELL"
默认情况下,Poetry 安装到特定于平台和用户的目录中:
~/Library/Application Support/pypoetry
在 MacOS 上。~/.local/share/pypoetry
在 Linux/Unix 上。%APPDATA%\pypoetry
在 Windows 上。# 更新至最新
$ poetry self update
# 指定要升级到的特定版本
$ poetry self update 1.5.1
可以通过config
命令进行配置,也可以在配置文件中配置
~/Library/Application\ Support/pypoetry
# 列出poetry配置,如果在poetry项目中会使用本地配置覆盖全局部分配置
$ poetry config --list
# 设置如果虚拟环境不存在,则自动创建虚拟环境
$ poetry config virtualenvs.create true
# 在项目根目录创建虚拟环境
$ poetry config virtualenvs.in-project true
# 不让虚拟环境有获取系统包的权限
$ poetry config virtualenvs.options.system-site-packages false
# 在创建新的虚拟环境时,环境中不会安装pip,生产环境非常建议
$ poetry config virtualenvs.options.no-pip true
# 在创建新的虚拟环境时,环境中不会安装setuptools,生产环境非常建议
$ poetry config virtualenvs.options.no-setuptools true
# poetry本地配置,实现针对于项目的设置,会在项目中创建poetry.toml文件
$ poetry config virtualenvs.create false --local
# 删除该字段的配置,自动恢复为默认值
$ poetry config virtualenvs.path --unset
$ poetry new poetry-demo
poetry-demo # 你的项目名称
├── README.md
├── poetry_demo # 真正的项目代码放在这里
│ └── __init__.py
├── pyproject.toml # 项目配置文件,不止能管理依赖版本,也可以在里面塞自己项目的配置
└── tests # 测试用代码放在这里
└── __init__.py
# 使用 src 布局进行创建,效果就是poetry_demo文件夹的名字改为src
$ poetry new --src <my-package>
$ cd <project-dir>
# 进入交互式界面配置pyproject.toml
$ poetry init
# 不要问任何互动问题
$ poetry init --no-interaction
Package name [项目名]: 这是问你要给项目/包起什么名字,敲回车键即默认为文件夹的名字
Version [0.1.0]: 项目/包的版本,如果你没有特别需求也可以直接敲回车
Description []: 你对这个项目的详细描述,只有在发布到PyPI时有用
Author [姓名 <邮箱>, n to skip]: 你的作者信息,输入n可以忽略不填
License []: 项目用什么开源协议,看你心情
Compatible Python versions [^3.x]: 项目能兼容哪些py版本,没有特殊需求就敲回车
Would you like to define your main dependencies interactively? (yes/no) [yes]: 询问你是否要在这个交互式界面直接添加/安装项目依赖,建议选no,因为没必要在这里添加
Would you like to define your development dependencies interactively? (yes/no) [yes]: 同样建议选no
Generated file ...... Do you confirm generation? (yes/no) [yes]: 显然这里直接敲回车yes就可以
pyproject.toml
文件,不会生成lock文件。pyproject.toml
文件中可以看到其中有一行「readme = "README.md"
」,此时项目目录中必须要有README.md
,否则会找不到并在未来使用中可能报错。我都直接刪除该行,比较省事。# 【推荐】
$ poetry install --sync --no-root --only main
# 从当前项目中读取pyproject.toml文件,解析依赖项并安装这些模块
$ poetry install
# 只安装依赖,将防止安装项目本身作为依赖项
$ poetry install --no-root
# 输出安装依赖操作,但不真正执行
$ poetry install --dry-run
# 只安装main环境的依赖,一般部署时使用
$ poetry install --only main
# 安装main+dev环境的依赖,一般用于开发
$ poetry install --with dev
# 同步当前环境并与lock文件完全一致,会自动卸载不在lock文件中的模块
$ poetry install --sync
如pyproject.toml
文件不存在,则会报错。
如不存在virtualenv,则会自动创建virtualenv,虚拟环境目录为{project-dir}/.venv
前提是配置了poetry config virtualenvs.create true
从当前项目中读取pyproject.toml
文件,解析依赖项并安装这些模块。如果当前目录中有poetry.lock
文件,它将使用lock那里的确切版本而不是解析它们。这可以确保使用该库的每个人都将获得相同版本的依赖项。
如果没有poetry.lock
文件,Poetry 会在依赖解析后创建一个lock文件。
poetry install
预设安装pyproject.toml
中的所有环境的所有包!所以如果你只想安装main环境的即 [tool.poetry.dependencies] 区块的包,请务必使用--only main
。
--with
:代表「和」的关系,也就是说会安装main的包也要安装指定环境的包。
# 根据pyproject.toml文件生成poetry.lock锁定文件,并不会安装任何的Python模块!!!
$ poetry lock
# 验证poetry.lock与pyproject.toml是否一致
$ poetry lock --check
当你自行修改了pyproject.toml
内容,比如变更特定包的版本(这是有可能的,尤其在手动处理版本冲突的时候),此时poetry.lock
的内容与pyproject.toml
出现了「脱钩」,必须让它依照新的pyproject.toml
内容更新、同步,使用指令poetry lock
。如此一来,才能确保手动修改的内容,也更新到poetry.lock
中,毕竟虚拟环境如果要重新建立,是基于poetry.lock
的内容来安装包,而非pyproject.toml
。
poetry.lock
相当于Poetry 的requirements.txt
。
poetry lock
指令,仅会更新poetry.lock
,「不会」同时安装包至虚拟环境。
因此,在执行完poetry lock
指令后,你必须再使用poetry install
来安装套件。
否则就会出现poetry.lock
和虚拟环境不一致的状况。
# 搜索远程索引上的包
$ poetry search <PackageName>
# 安装Python的模块
$ poetry add <PackageName>
# 为开发分组安装Python的模块
$ poetry add <PackageName> --group=dev
# 安装特定版本的Python的模块
$ poetry add <PackageName>=2.0.5
# 允许 >=2.0.5, <3.0.0 的版本
$ poetry add <PackageName>@^2.0.5
# 允许 >=2.0.5, <2.1.0 的版本
$ poetry add <PackageName>@~2.0.5
# 允许 >=2.0.5 的版本
$ poetry add "pendulum>=2.0.5"
# 获取已存在Python包的最新版本
$ poetry add <PackageName>@latest
# 安装本地Python模块
$ poetry add ../my-package/dist/my_package-0.1.0.whl
# 如果您要安装的软件包提供了额外功能,您可以在添加软件包时指定它们
$ poetry add "requests[security,socks]"
# 将包添加到dev依赖项组中,组不存在则会自动创建
$ poetry add <PackageName> --group dev
# poetry不直接支持这一点,可以使用Shell命令将其作为参数传递给 Poetry 的 add 命令
$ cat requirements.txt | xargs poetry add
# 使用pypi源安装此模块
$ poetry add --source pypi <PackageName>
如不存在virtualenv,则会自动创建virtualenv,前提是配置了poetry config virtualenvs.create true
会自动配置pyproject.toml
如pyproject.toml
文件不存在则会报错。
在以有pyproject.toml 文件的情况下,如不存在poetry.lock
,则会自动创建poetry.lock
如果您尝试添加已存在的包,您将收到错误消息。
有些包,比如pytest
、flake8
等等,只会在开发环境中使用,产品的部署环境并不需要。Poetry 允许你区分这两者,将上述的包安装至group.dev.dependencies
区块,方便让你轻松建立一份「不包含」group.dev.dependencies
开发包的安装清单。需使用--group
参数。明确区分开发环境专用的套件,我认为非常必要。
常见的group.dev.dependencies
区块项目,例示如下:
# poetry1.1老版本是[tool.poetry.dev-dependencies]
[tool.poetry.group.dev.dependencies]
flake8 = "4.0.1"
yapf = "0.32.0"
pytest = "7.1.2"
pytest-django = "4.5.2"
pytest-cov = "3.0.0"
pytest-env = "0.6.2"
pytest-sugar = "0.9.4"
pre-commit = "2.20.0"
当你使用poetry add
指令时,Poetry 会自动依序帮你做完这三件事:
pyproject.toml
。pyproject.toml
的内容,更新poetry.lock
。(相当于poetry lock
)poetry.lock
的内容,更新虚拟环境。(相当于poetry install
)当你不是使用poetry add
指令,而是直接修改pyproject.toml
时,此时上述的第 2、3 步都不会自动执行。但通常你手动修改 toml 档最终都是为了变更虚拟环境,所以更新完pyproject.toml
后,我们还要再使用poetry lock
然后再执行poetry install
指令才行!
poetry add
只会在pyproject.toml
中写入「主包」即top-level的包名,但cat requirements.txt | xargs poetry add
这样的import方式相当于把requirements.txt
中的所有包,都当作主包来add
了!
因为Poetry对套件的版本冲突比较敏感,所以仍有机会出现错误,只能照着错误讯息手动修正。毕竟在requirements.txt
中无从区分主包与依赖包,都是「一视同仁」地列出。但如此做法也让项目的包失去主从之分,日后要移除主包时,需要花额外的心力去区分主从。
# 更新全部「可能可以更新」的包,这相当于删除poetry.lock文件并install再次运行。
$ poetry update
# 更新仅指定的「可能可以更新」的包
$ poetry update <PackageName>
pyproject.toml
文件中指定的版本约束之外的依赖项的版本。所以如果要更新需要先修改 pyproject.toml
文件中指定的版本约束,而后再进行更新。pyproject.toml
中的设定。# 查看poetry.lock中的依赖
$ poetry show
# 查看指定模块的信息
$ poetry show <PackageName>
# 树形结构查看项目安装的依赖
$ poetry show -t
# 显示项目依赖包的当前版本和最新版本
$ poetry show -l
# 查看可以更新的依赖
$ poetry show --outdated
poetry show
类似pip list
,这里的清单内容并不是来自于虚拟环境,这点和pip不同,而是来自于poetry.lock
的内容。poetry.lock
也有不一致的时候,比如你使用了pip install
指令安装包,就不会记载在poetry.lock
中,那poetry show
自然也不会显示。poetry.lock
文件不存在,则会报错并提示运行 poetry lock
命令进行创建。pyproject.toml
文件中。-t
会导致颜色不准,即未安装显示已安装。(发现的Bug,已提issue)# 从当前已安装软件包列表中删除软件包
$ poetry remove <PackageName>
# 从dev依赖项组中删除包
$ poetry remove <PackageName> --group dev
pip uninstall
只会移除你所指定的包,而不会连同依赖包一起移除。Flask
和Black
这两个top-level包都共同依赖click
这个包,如果我们使用poetry remove flask
则不会移除依赖包click
,因为有依赖解析,Poetry 知道Black
还需要click
!所以不能移除。# 将lock锁定文件导出为其他格式
$ poetry export -f requirements.txt --output requirements.txt
# 不带哈希散列
$ poetry export --without-hashes -f requirements.txt --output requirements.txt
# 仅输出[tool.poetry.group.dev.dependencies]的包
$ poetry export --without-hashes -f requirements.txt --output requirements.txt --only dev
poetry export
预设只会输出pyproject.toml
中的[tool.poetry.dependencies]
区块的包!因为大部分时候我们并不需要输出开发用包。# 会在dist目录下生成当前版本的.whl和.tar.gz包
$ poetry build
# 将构建的包发布到远程存储库中
$ poetry publish
$ poetry publish -u <username> -p <password>
# Poetry会为你生成一个带有项目名的虚拟环境的新Shell并进入
$ poetry shell
# 显示当前激活的环境信息
$ poetry env info
# 使用 run 命令在虚拟环境中执行给定的命令
$ poetry run python <your_script.py>
# 验证 pyproject.toml 文件的结构,并在存在任何错误时返回详细报告
$ poetry check
pyproject.toml
文件中配置,即只针对当前项目有效。default
> primary
> implicit PyPI
> supplemental
> explicit
default
:primary
:如果priority
未定义,则源被视为primary
。implicit
:隐式源;pypi默认就是这个。supplemental
:补充源;可以有多个补充包源。仅当没有其他(更高优先级)源产生兼容的包分发时,才会搜索配置为补充的包源。explicit
:显式源;即仅对于明确指定其来源的包才会使用显式源。explicit
,PyPI将自动禁用。# 显示项目中所有已配置源的信息
$ poetry source show
# 添加aiyun的源并设置为优先级最高的default,这会完全禁用pypi源
$ poetry source add --priority=default aliyun https://mirrors.aliyun.com/pypi/simple/
# 所以为了同时可以使用PyPI源这里最好也配置
$ poetry source add --priority=primary PyPI
# 列出Poetry的可用缓存
$ poetry cache list
# 从缓存的存储库中删除包
$ poetry cache clear pypi --all
# 从 pyproject.toml 中删除已配置的源代码。
$ poetry source remove aliyun
这是最理想的状态,没有过去的「包袱」,可谓是最能轻松采用Poetry 的情境。
我的使用顺序是:
poetry init
:初始化,只会在当前目录中新建一个pyproject.toml
文件。poetry env use python
(可省):建立项目的虚拟环境。poetry shell
:使用此指令进入虚拟环境。poetry add
:安装指定包并写入虚拟环境。必要时使用--group dev
参数,使其安装至dev 区块。poetry remove
:移除指定包,若是移除dev区块的套件,需要加上--group dev
参数。极为常见的需求
poetry init
:初始化,只会在当前目录中新建一个pyproject.toml
文件。poetry shell
:使用此指令进入虚拟环境。cat requirements.txt | xargs poetry add
requirements.txt
中的所有包,都当作主包来add
了!requirements.txt
中无从区分主包与依赖包,都是「一视同仁」地列出。但如此做法也让项目的包失去主从之分,日后要移除主包时,需要花额外的心力去区分主从。第一步当然是git clone
专案,此时专案中已经有Poetry 所需的必要资讯了——也就是pyproject.toml
和poetry.lock
。
你还缺少的仅仅是虚拟环境。
poetry shell
:使用此指令进入虚拟环境。
如果使用本指令时虚拟环境尚未建立或已移除,则会直接自动帮你建立虚拟环境并进入。
poetry install
:因为是旧专案,不需要init
,会直接依poetry.lock
记载的套件版本安装到虚拟环境中!类似npm install
。
.venv
文件夹即可。poetry env use python
或poetry shell
建一个新的就好。因为启动容器后需要先安装Poetry 到全域,或打包一个带有Poetry 的image,两者都会增加新的耦合与依赖,我觉得并不妥当。
解决方案:
requirements.txt
,Docker 部署环境就继续使用这个旧方案即可。Poetry Command | 解释 |
---|---|
$ poetry --version |
显示您的 Poetry 安装版本。 |
$ poetry new |
创建一个新的Poetry项目。 |
$ poetry init |
将 Poetry 添加到现有项目中。 |
$ poetry run |
使用 Poetry 执行给定的命令。 |
$ poetry add |
添加一个包pyproject.toml 并安装它。 |
$ poetry update |
更新项目的依赖项。 |
$ poetry install |
安装依赖项。 |
$ poetry show |
列出已安装的软件包。 |
$ poetry lock |
将最新版本的依赖项固定到poetry.lock . |
$ poetry lock --no-update |
刷新poetry.lock 文件而不更新任何依赖版本。 |
$ poetry check |
验证pyproject.toml 。 |
$ poetry config --list |
显示 Poetry 配置。 |
$ poetry env list |
列出项目的虚拟环境。 |
$ poetry export |
导出poetry.lock 为其他格式。 |
pyenv local
和poetry env use
两大指令即可。# 安装CPython 3.9.17
$ pyenv install 3.9.17
# 创建项目目录并进入
$ mkdir my-project && cd my-project
# 为当前项目设置使用Python 3.9.17,会创建.python-version文件
$ pyenv local 3.9.17
# 只生成pyproject.toml文件
$ poetry init
# 进入虚拟环境(不存在会自带创建虚拟环境)
$ poetry shell
# 从当前项目中读取pyproject.toml文件,解析依赖项并安装这些模块,会自动生成lock文件
$ poetry install
https://blog.kyomind.tw/python-poetry/
https://blog.kyomind.tw/poetry-pyenv-practical-tips/