python 的版本、依赖包、虚拟环境管理

我并不是 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 虚拟环境#

解决第二个问题的方案,是虚拟环境。相关工具: virtualenvvenv(python 3.3 之后自带)

虚拟环境关联了 python 版本和安装的依赖包。
回到一个原始的问题,在执行 python 命令时,操作系统是如何找到 python 命令的?答案就是 PATH 环境变量。python 虚拟环境,就是将所需要的内容复制一份(实际通常使用软链接的方式),在切换到虚拟环境时,就将当前进程的 PATH 环境变量修改一下,添加当前虚拟环境的目录到 PATH 中,这样,执行 python 命令时,执行的就是虚拟环境中的,而不是默认安装的那个。

所以,这就是为什么需要先激活虚拟环境,进入虚拟环境的命令行环境中,就是修改了当前进程的环境变量。激活虚拟环境这个动作,并不是全局的,仅在当前进程生效,并不会影响其它地方。

# 创建虚拟环境
# 会在当前目录下,创建一个 myenv1 的文件夹,里面保存的就是这个虚拟环境下的 python 内容
python -m venv myenv1

# 激活虚拟环境
# 执行这个目录下的 activate 脚本,
myenv1\Scripts\activate # windows
source myenv1/bin/activate # linux

# 退出虚拟环境
deactivate

在使用 poetry 进行项目管理时,可以不显式激活虚拟环境,本质上,是 poetry 拦截了执行进程的环境变量等相关设置。
所以,换句话说,需要使用 poetry 来执行脚本。如果在命令行窗口直接使用 python 命令来执行脚本,使用的还是全局的配置。

📺安装不算完事,只有理解了虚拟环境才算真正掌握 Python 环境_哔哩哔哩

感受如下 python .\__init__.pypoetry run python .\__init__.py 的区别。

python .\__init__.py

Python 可执行文件路径: 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_project1
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\python313.zip
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\DLLs
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\Lib
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\Lib\site-packages
poetry run python .\__init__.py

Python 可执行文件路径: 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_project1
  C:\Users\jgrass\Desktop\practice\python\my_project1\.venv\Scripts\python313.zip
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\DLLs
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1\Lib
  C:\Users\jgrass\.pyenv\pyenv-win\versions\3.13.1
  C:\Users\jgrass\Desktop\practice\python\my_project1\.venv
  C:\Users\jgrass\Desktop\practice\python\my_project1\.venv\Lib\site-packages
  C:\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 和虚拟环境(如 virtualenvvenv)的组合时,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 setup

setup(
    name='my_project',
    version='0.1',
    install_requires=[
        'requests==2.25.1',
        'flask==1.1.2',
    ],
)

安装依赖:

pip install .

3.Pipfile 和 Pipfile.lock#

PipfilePipfile.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 项目的配置。它不仅可以用于依赖管理,还可以配置构建工具(如 setuptoolspoetry)和其他工具。

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:适合创建可分发包的项目,管理依赖和元数据。
  • PipfilePipfile.lock:现代化依赖管理,适合需要锁定依赖版本的一致性项目。
  • pyproject.toml:统一配置文件,适合使用现代构建工具(如 poetry)的项目。
  • Conda 环境:强大的包和环境管理,适合数据科学和机器学习项目。

在搜索 pipenvpoetry 时,感觉 poetry 优势很明显。

在使用 pipenv 或者 poetry 时,使用它们安装依赖包时,会自动为项目创建虚拟环境,在切换项目时,需要执行 pipenv shell 或者 poetry shell 来激活虚拟环境。

pipenv 或者 poetry 等工具,底层都是使用 virtualenvvenv 来管理虚拟环境。

🍉 工具的使用#

pyenv 是 python 版本管理工具,与其他工具是独立的。

pipenvpoetryConda 这个工具的功能是重合的,都集成了包管理,虚拟环境管理等功能,同一个项目,使用一个就可以。

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.1
  These 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 globally
    accessible until your PATH is updated. Run `pipx ensurepath` to automatically add it, or manually modify your PATH
    in 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 file

Installing the current project: my-project1 (0.1.0)

poetry env info 可以快速查看当前项目的虚拟环境信息,包括路径和是否激活
poetry env info --path 可以直接查看虚拟环境的路径
poetry env list 查看虚拟环境列表

配置 virtualenvs.in-projecttrue 后,可以更直观地管理虚拟环境

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 退出。

在命令行中,可以使用 whichwhere 命令检查当前使用的 Python 解释器路径:

which python

# 或在 Windows 上:
where python # cmd
Get-Command python # powershell

如果输出的路径指向虚拟环境中的 Python 解释器,则表示当前激活了虚拟环境。

使用 Poetry 命令:Poetry 提供了一些命令来管理和检查虚拟环境。你可以使用以下命令查看当前项目的虚拟环境路径:

poetry env info --path

这将输出当前项目的虚拟环境路径。如果没有激活虚拟环境,则不会有输出。

pipenv#

Pipenv: Python Dev Workflow for Humans

这个视频讲的比较清楚

📺[Python] pipenv 包管理 虚拟环境管理_哔哩哔哩

安装

pip install pipenv --user

# 需要将类似如下路径添加的 PATH 环境变量
C:\Users\jgrass\AppData\Roaming\Python\Python313\Scripts
# 初始化 pipenv 环境:在项目目录中运行以下命令来初始化一个新的 Pipenv 环境并创建一个 Pipfile:
pipenv install

# 安装依赖包:使用 pipenv 来安装项目所需的包。例如:
pipenv install requests

# 激活虚拟环境:要在项目中使用这个虚拟环境,可以运行:
# 这会启动一个新的 shell,其中虚拟环境被激活
pipenv shell

# 退出虚拟环境:完成工作后,可以输入以下命令退出虚拟环境的 shell:
exit

# 不进入虚拟环境,可以直接通过 pipenv run 来使用当前目录的虚拟环境运行 python 脚本
pipenv run python hello.py

# 也可以先进入虚拟环境,再执行命令
pipenv shell
python hello.py

# 删除当前目录的虚拟环境
pipenv --rm

作者:JasonGrass

出处:https://www.cnblogs.com/jasongrass/p/18678663

版权:本作品采用「署名 4.0 国际」许可协议进行许可。

posted @   J.晒太阳的猫  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示