Python 环境最容易乱:系统 Python、Homebrew Python、Anaconda、pyenv、pipenv、项目 .venv、全局 pip install,时间久了以后,连自己都不知道某个命令到底跑在哪个解释器上。
我现在更倾向于把个人项目统一收敛到 uv:项目内虚拟环境、pyproject.toml、uv.lock、uv run,尽量不再依赖全局 pip 和零散环境。
为什么要收敛
环境混乱的典型症状是:
- 本机能跑,换目录就不能跑。
pip install成功,但程序仍然ModuleNotFoundError。- 不知道依赖装到了哪个 Python。
- requirements 里版本不稳定。
- 全局安装的包影响另一个项目。
- 旧项目依赖 conda、pyenv、pipenv 混在一起。
这些问题不是某个包的问题,而是环境边界不清楚。每个项目应该有自己的依赖、自己的虚拟环境和可重复执行的命令。
uv 的基本定位
uv 可以管理 Python 项目、虚拟环境、依赖安装和命令运行。日常常用命令不多:
uv init my-python-demo
cd my-python-demo
uv add requests
uv run python main.py
如果只是临时执行一个命令行工具,可以用:
uvx ruff --version
uvx 适合临时工具,不污染全局环境。
新项目怎么建
新项目建议直接用:
uv init demo
cd demo
uv add flask
uv add --dev pytest ruff
uv run python main.py
uv run pytest
项目里保留:
pyproject.toml:声明项目和依赖。uv.lock:锁定依赖版本。.venv/:本地虚拟环境,不提交 Git。
对于应用、脚本工具和长期维护项目,uv.lock 建议提交。这样下次恢复环境时,依赖版本更稳定。
为什么不继续全局 pip
全局 pip install 的问题是边界模糊。你不知道某个包是给哪个项目装的,也不知道升级一个包会不会影响另一个项目。
更稳的方式是:
uv add package-name
uv run python your_script.py
如果确实要使用 pip,也尽量在项目虚拟环境里:
uv pip install -r requirements.txt
不要在脚本里写死 /usr/bin/python、/opt/homebrew/bin/python3 或某个本机 .venv/bin/python 绝对路径。项目命令统一通过 uv run。
旧项目怎么接管
旧项目如果只有 requirements.txt,可以先不急着重构:
cd old-project
uv venv
uv pip install -r requirements.txt
uv run python -m your_module
确认项目还要继续维护后,再迁到 pyproject.toml:
uv init
uv add requests flask openpyxl
uv add --dev pytest ruff
uv sync
迁移时不要一口气改业务代码。先确保原项目能用 uv 跑起来,再整理依赖和入口。
conda、pyenv、pipenv 怎么处理
我的默认规则是:
- pyenv:不作为默认版本管理工具,除非旧项目明确需要特定 Python 版本。
- conda:不作为普通项目默认方案,数据科学、GPU、重原生依赖项目可以例外。
- pipenv:新项目不再使用,旧项目维护时优先迁到 uv。
- pip:只在项目环境内使用,避免全局安装。
这不是说这些工具不好,而是个人项目里工具太多会增加维护成本。能统一就统一。
加密库的一个坑
Python 里不要安装名为 Crypto 的包。很多场景真正需要的是 pycryptodome。
推荐在项目环境内执行:
uv add pycryptodome
如果旧环境装错了,可以先清理:
uv pip uninstall Crypto
uv pip uninstall pycryptodome
uv add pycryptodome
这类问题也说明了项目隔离的重要性:装错包时,只影响当前项目,不污染全局。
一个实用约定
个人项目可以统一成这样:
project/
├── pyproject.toml
├── uv.lock
├── .venv/ # 不提交
├── src/ 或 app/
└── README.md
README 里写清:
- Python 版本。
- 如何安装依赖。
- 如何启动。
- 如何测试。
命令统一用:
uv sync
uv run pytest
uv run python main.py
最后看目标
环境管理的目标不是追新工具,而是让项目可恢复、可运行、可解释。uv 的好处是把虚拟环境、依赖和命令入口收在一条线里。
当你不再需要猜“这个 Python 到底是哪一个”,环境管理就轻松很多。




