我并不是 python 开发者,但突然对这个话题感兴趣,所以就和 AI 聊了起来,以下是一些聊天笔记。
注意,这里可能有部分内容是过时或者错误的,以官方文档或者实际效果为准。
在电脑上安装 python 之后,就可以直接在控制台执行 python 脚本了。但此时有两个问题,
1 python 的版本是固定的,如果有多个项目,不同的项目可能需要不同的 python 版本。
2 全局状态下,python 的包管理是会冲突的,同一个包,只能有一个版本存在,如果不同项目依赖于不同的版本的包,就会有冲突。
🍉 python 版本管理
解决第一个问题的工具,是 python 版本管理,如 pyenv
pyenv/pyenv: Simple Python version management
不过 pyenv
并不支持 Windows 系统,Windows 系统可以使用 pyenv-win/pyenv-win: pyenv for Windows.
类似的,对于 node.js,也有 nvm, n 这样的版本管理工具
pyenv-win
不推荐通过 scoop 安装,安装的版本似乎是有问题的。直接使用 powershell 脚本安装。
pyenv-win/docs/installation
# 安装
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "./install-pyenv-win.ps1"; &"./install-pyenv-win.ps1"# 升级
&"${env:PYENV_HOME}\install-pyenv-win.ps1"
PS scoop 自带了 python 版本管理功能,不过功能比较简单
Switching Ruby, Python and PHP Versions · ScoopInstaller/Scoop Wiki
🍉 python 虚拟环境
解决第二个问题的方案,是虚拟环境。相关工具 virtualenv
或 venv
(python 3.3 之后自带)
虚拟环境关联了 python 版本和安装的依赖包。虚拟环境是一个全局的概念,在同一时刻,电脑上只有一个虚拟环境是激活状态,此时,在这个环境下安装的包,都被这个环境管理。
如果有另一个项目依赖不同的 python 版本和依赖包,则切换 python 版本后,在那个版本创建一个新的虚拟环境。
因为虚拟环境是一个全局的概念,项目A和项目B的虚拟环境不一致的话,切换项目时,需要先手动切换到对应的虚拟环境。(当然,也可以使用工具进行自动切换)
在没有激活任何虚拟环境时,就处于默认的全局环境中。
在使用 poetry 进行项目管理时,可以创建不影响全局的虚拟环境,仅影响当前项目。本质上,是 poetry 拦截了执行进程的环境变量等相关设置。
所以,换句话说,需要使用 poetry 来执行脚本。如果在命令行窗口直接使用 python 命令来执行脚本,使用的还是全局的配置。
感受如下 python .\__init__.py
和 poetry run python .\__init__.py
的区别。
python .\__init__.pyPython 可执行文件路径: C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\python.exe
Python 版本: 3.13.1
完整版本信息: 3.13.1 (tags/v3.13.1:0671451, Dec 3 2024, 19:06:28) [MSC v.1942 64 bit (AMD64)]
操作系统平台: Windows
模块搜索路径:C:\Users\jgrass\Desktop\practice\python\my_project1\my_project1C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\python313.zipC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\DLLsC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\LibC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\Lib\site-packages
poetry run python .\__init__.pyPython 可执行文件路径: C:\Users\jgrass\Desktop\practice\python\my_project1\.venv\Scripts\python.exe
Python 版本: 3.13.1
完整版本信息: 3.13.1 (tags/v3.13.1:0671451, Dec 3 2024, 19:06:28) [MSC v.1942 64 bit (AMD64)]
操作系统平台: Windows
模块搜索路径:C:\Users\jgrass\Desktop\practice\python\my_project1\my_project1C:\Users\jgrass\Desktop\practice\python\my_project1\.venv\Scripts\python313.zipC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\DLLsC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\LibC:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1C:\Users\jgrass\Desktop\practice\python\my_project1\.venvC:\Users\jgrass\Desktop\practice\python\my_project1\.venv\Lib\site-packagesC:\Users\jgrass\Desktop\practice\python\my_project1
import sys
import platform# 获取 Python 解释器的可执行文件路径
python_executable_path = sys.executable
print(f"Python 可执行文件路径: {python_executable_path}")# 获取 Python 版本信息
python_version = platform.python_version()
print(f"Python 版本: {python_version}")# 获取完整的版本信息,包括编译器和构建时间
python_version_info = sys.version
print(f"完整版本信息: {python_version_info}")# 获取系统平台信息
system_platform = platform.system()
print(f"操作系统平台: {system_platform}")# 获取 Python 搜索模块的路径(即 sys.path)
python_module_search_paths = sys.path
print("模块搜索路径:")
for path in python_module_search_paths:print(f" {path}")
所以,在引入虚拟环境这个概念之后,搞清楚在当前执行环境,究竟是在哪个环境,使用的是哪个解释器就很关键。
python 版本管理于虚拟环境的关系
在使用 pyenv
和虚拟环境(如 virtualenv
或 venv
)的组合时,Python 的版本通常由虚拟环境本身来决定,而不是由全局的 Python 版本控制工具(如 pyenv)直接影响。
场景举例:
使用 pyenv 设置当前 Python 的版本为 3.7。
创建一个虚拟环境 env1。
激活虚拟环境 env1。
使用 pyenv 将全局或本地 Python 版本切换到 3.11。
在激活的虚拟环境 env1 中检查 Python 的版本。
结果分析:
在这种情况下,当你激活虚拟环境 env1 时,虚拟环境会使用它创建时指向的 Python 二进制文件(即创建虚拟环境时的 Python 版本)。这意味着:
虚拟环境 env1 是使用 Python 3.7 创建的,因此激活虚拟环境后,命令行中的 python 版本仍然是 3.7,不会受到 pyenv 切换全局或本地 Python 版本的影响。
虚拟环境是一个独立的沙盒环境,它会以创建时的 Python 解释器为基础,因此切换 pyenv 的版本不会改变虚拟环境的行为。
也就是说,当激活 env1 后检查 Python 的版本,输出的应该是:Python 3.7.x
为什么会这样?
虚拟环境的本质:
虚拟环境在创建时会复制(或者软链接)当前 Python 解释器的核心文件到虚拟环境目录下,并将虚拟环境的 bin(Linux/Mac)或 Scripts(Windows)目录调整为优先搜索路径。
因此,当虚拟环境被激活时,系统会优先使用虚拟环境内的 Python 解释器,而不是全局版本。
pyenv 的作用范围:
pyenv 管理的是全局或者当前目录下的 Python 版本,而虚拟环境则是一个独立的环境。一旦激活虚拟环境,pyenv 对 Python 版本的控制就会被虚拟环境屏蔽。
如果你想验证上述行为,可以尝试以下步骤:
# 使用 pyenv 设置 Python 版本为 3.7
pyenv shell 3.7# 查看当前 Python 版本,应该是 3.7
python --version# 创建虚拟环境
python -m venv env1# 激活虚拟环境
source env1/bin/activate # Linux/Mac
# 或
env1\Scripts\activate # Windows# 再次查看 Python 版本,应该是 3.7
python --version# 退出虚拟环境
deactivate# 切换 pyenv 的版本到 3.11
pyenv shell 3.11# 在未激活虚拟环境时,Python 版本应该是 3.11
python --version# 重新激活虚拟环境 env1
source env1/bin/activate # Linux/Mac
# 或
env1\Scripts\activate # Windows# 检查激活虚拟环境后的 Python 版本,应该仍是 3.7
python --version
总结:虚拟环境会记录创建时的 Python 版本,并在激活后使用该版本的解释器。即使你用 pyenv 切换了全局或本地的 Python 版本,虚拟环境的 Python 版本不会受到影响。
🍉 python 包管理
虽然有了虚拟环境,可以解决不同项目之间依赖的冲突问题,但是对于一个具体的项目,如何管理其依赖呢?比如前端有 package.json,rust 有 cargo.toml,C# 有 csproj 文件。
Python 的方案有点多,不同的工具,使用的是不同的方式。
Python 的包管理方案随着时间的推移不断发展,以适应不断变化的需求和生态系统。以下是从历史演进路径介绍的不同方案:
1. requirements.txt
requirements.txt
是最早、最常用的 Python 项目依赖管理方式。这个文件简单地列出了项目中所有需要的依赖包及其版本。
requests==2.25.1
flask==1.1.2
2. setup.py
setup.py
是用于创建可分发包(distributable package)的标准文件。它不仅可以用于管理项目依赖,还可以定义项目的元数据和打包信息。
// setup.py
from setuptools import setupsetup(name='my_project',version='0.1',install_requires=['requests==2.25.1','flask==1.1.2',],
)
安装依赖:
pip install .
3.Pipfile 和 Pipfile.lock
Pipfile
和 Pipfile.lock
是由 Pipenv
引入的,用于替代 requirements.txt,提供更现代化、更安全的依赖管理方式。Pipfile 记录项目的依赖,而 Pipfile.lock 锁定依赖的具体版本,确保环境一致性。
Pipfile 文件示例:
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true[packages]
requests = "*"
flask = "*"[dev-packages]
pytest = "*"[requires]
python_version = "3.9"
4. pyproject.toml
pyproject.toml
是 PEP 518 引入的标准文件,旨在统一 Python 项目的配置。它不仅可以用于依赖管理,还可以配置构建工具(如 setuptools
、poetry
)和其他工具。
pyproject.toml 文件示例:
[tool.poetry]
name = "my_project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"][tool.poetry.dependencies]
python = "^3.9"
requests = "^2.25.1"
flask = "^1.1.2"[tool.poetry.dev-dependencies]
pytest = "^6.2.2"[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
5. Conda 环境
Conda
是一个跨平台的包和环境管理系统,支持 Python 以及其他编程语言。Conda 提供了强大的依赖管理和环境隔离功能,特别适用于数据科学和机器学习项目。
使用方法
创建环境并安装依赖:
environment.yml 文件示例:
name: myenv
channels:- defaults
dependencies:- python=3.9- requests=2.25.1- flask=1.1.2- pip:- pytest==6.2.2
python 包管理小结
不同的包管理方案适用于不同的场景和需求:
requirements.txt
:简单、广泛使用,适合小型项目。setup.py
:适合创建可分发包的项目,管理依赖和元数据。Pipfile
和Pipfile.lock
:现代化依赖管理,适合需要锁定依赖版本的一致性项目。pyproject.toml
:统一配置文件,适合使用现代构建工具(如 poetry)的项目。Conda
环境:强大的包和环境管理,适合数据科学和机器学习项目。
在搜索 pipenv
和 poetry
时,感觉 poetry
优势很明显。
在使用 pipenv
或者 poetry
时,使用它们安装依赖包时,会自动为项目创建虚拟环境,在切换项目时,需要执行 pipenv shell
或者 poetry shell
来激活虚拟环境。
pipenv
或者 poetry
等工具,底层都是使用 virtualenv
或 venv
来管理虚拟环境。
🍉 工具的使用
pyenv
是 python 版本管理工具,与其他工具是独立的。
pipenv
、poetry
、Conda
这个工具的功能是重合的,都集成了包管理,虚拟环境管理等功能,同一个项目,使用一个就可以。
pipx
pypa/pipx: Install and Run Python Applications in Isolated Environments
一个 python 全局工具包安装管理工具,使用 pipx
安装 poetry
。
pipx install poetry
installed package poetry 2.0.1, installed using Python 3.13.1These apps are now globally available- poetry.exe
⚠️ Note: 'C:\Users\jgrass\.local\bin' is not on your PATH environment variable. These apps will not be globallyaccessible until your PATH is updated. Run `pipx ensurepath` to automatically add it, or manually modify your PATHin your shell's config file (e.g. ~/.bashrc).
done! ✨ 🌟 ✨
然后运行 pipx ensurepath
,将 C:\Users\jgrass\.local\bin
添加到环境变量,这样才可以使用 poetry
。
Success! Added C:\Users\jgrass\.local\bin to the PATH environment variable.Consider adding shell completions for pipx. Run 'pipx completions' for instructions.You will need to open a new terminal or re-login for the PATH changes to take effect. Alternatively, you can source
your shell's config file with e.g. 'source ~/.bashrc'.Otherwise pipx is ready to go! ✨ 🌟 ✨
这里还提示,运行 pipx completions
添加代码补全功能。
pipx
安装的工具不受 pyenv
切换版本的影响,因为 pipx
在独立的虚拟环境中管理这些工具,并通过固定路径将它们链接到系统的 PATH 环境变量中。
这确保了无论你切换到哪个 Python 版本,pipx 管理的工具都能正常工作。
pipx
安装工具时使用的 Python 版本是你在运行 pipx install
命令时的系统默认 Python 版本。
它不受当前激活的虚拟环境影响,但你可以通过 pyenv
或其他方式切换系统的 Python 版本来影响 pipx
创建的虚拟环境。
可以使用 pipx list
来查看 pipx
安装的工具,以及其基于的 Python 版本。
如果要在新的 Python 版本中安装工具,在使用 pyenv
切换版本之后,可以使用 pipx reinstall <tool>
重新安装工具。
poetry
使用 poetry 创建项目 poetry new my_project1
进入项目目录,执行 poetry install
自动创建一个虚拟环境,并安装 pyproject.toml 文件中指定的所有依赖项(如果有的话)。
Creating virtualenv my-project1-lE7ezTdX-py3.13 in C:\Users\jgrass\AppData\Local\pypoetry\Cache\virtualenvs
Updating dependencies
Resolving dependencies... (0.1s)Writing lock fileInstalling the current project: my-project1 (0.1.0)
poetry env info
可以快速查看当前项目的虚拟环境信息,包括路径和是否激活
poetry env info --path
可以直接查看虚拟环境的路径
poetry env list
查看虚拟环境列表
配置 virtualenvs.in-project
为 true
后,可以更直观地管理虚拟环境
Poetry 默认会将虚拟环境存储在用户目录下的 .cache/pypoetry/virtualenvs/
中,但你也可以更改其行为,使虚拟环境直接创建在项目目录下。可以通过以下命令设置:
poetry config virtualenvs.in-project true
,设置之后,如果之前已经创建了这个项目的虚拟环境,则需要先删除 poetry env remove python
,
然后重新安装 poetry env use python
/ poetry install
配置完成后,虚拟环境将会创建在项目目录内的 .venv
文件夹中。这样可以更方便地找到虚拟环境。
poetry 入门完全指南 | 正心全栈编程
poetry shell
命令默认不可用,在 Poetry 2 被移除了,需要安装插件。
Commands | Documentation | Poetry - Python dependency management and packaging made easy
可以使用 poetry env use python
来进入独立的 shell 虚拟环境,并使用 exit
退出。
在使用 Poetry 时,激活的虚拟环境不会影响全局的虚拟环境设置。Poetry 会为每个项目创建独立的虚拟环境,这些虚拟环境是独立于全局 Python 环境的。
在全局命令行中,你可以通过以下几种方法检查当前是否激活了虚拟环境,以及激活的是哪个虚拟环境:
检查环境变量:激活虚拟环境时,通常会设置 VIRTUAL_ENV
环境变量来指示当前正在使用的虚拟环境。你可以通过以下命令检查这个变量:
echo $VIRTUAL_ENV
如果输出为空,则没有激活虚拟环境。如果输出的是一个路径,则该路径指向当前激活的虚拟环境。
使用 which
或 where
命令:
你可以检查当前使用的 Python 解释器路径:
which python# 或在 Windows 上:
where python
如果输出的路径指向虚拟环境中的 Python 解释器,则表示当前激活了虚拟环境。
使用 Poetry 命令:Poetry 提供了一些命令来管理和检查虚拟环境。你可以使用以下命令查看当前项目的虚拟环境路径:
poetry env info --path
这将输出当前项目的虚拟环境路径。如果没有激活虚拟环境,则不会有输出。