Python环境与包管理
Python 项目最容易出问题的地方往往不是语法,而是环境和依赖。同一台电脑上可能有多个 Python 解释器,同一个包也可能有多个版本;如果不隔离环境,就会出现“我电脑能跑、你电脑不能跑、服务器也不能跑”的问题。
学完本页后,你应该能做到:
- 说清楚 Python 解释器、pip、虚拟环境、项目依赖之间的关系。
- 会在 Windows、macOS、Linux 上创建和激活虚拟环境。
- 知道
pip install到底把包装到了哪里。 - 会用
requirements.txt复现环境。 - 理解
pyproject.toml、Poetry、uv 这类现代包管理工具解决什么问题。 - 能排查“包安装了但导入失败”“pip 装错环境”“版本冲突”“AI 环境 CUDA 不匹配”等问题。
为什么必须理解环境
一个 Python 项目能运行,至少依赖四层东西:
flowchart TD
A["操作系统"] --> B["Python 解释器"]
B --> C["虚拟环境 venv"]
C --> D["第三方依赖包"]
D --> E["项目代码"]每层都可能出问题:
| 层级 | 常见问题 |
|---|---|
| 操作系统 | Windows/Linux 路径不同、权限不同、动态库不同 |
| Python 解释器 | 版本不同,语法或标准库能力不同 |
| 虚拟环境 | 没激活、激活错、删了依赖 |
| 第三方包 | 版本冲突、装到全局、缺少二进制依赖 |
| 项目代码 | import 路径错误、配置缺失 |
商业项目里,环境管理的目标不是“本机能跑”,而是让同事、测试机、生产容器都能稳定复现。
Python、pip、venv 的关系
很多初学者把 python 和 pip 当成两个独立工具,其实 pip 总是属于某个 Python 解释器。
flowchart TD
A["Python 3.10 解释器"] --> B["它自己的 pip"]
A --> C["site-packages 依赖目录"]
D["Python 3.12 解释器"] --> E["它自己的 pip"]
D --> F["另一个 site-packages 依赖目录"]如果你运行:
pip install requests你必须确认这个 pip 属于当前项目要用的 Python。否则可能出现:安装成功了,但运行代码时仍然 ModuleNotFoundError。
更稳的写法是:
python -m pip install requests含义:用当前这个 python 去执行它绑定的 pip 模块。这样能避免 pip 指向另一个解释器。
查看当前 Python 环境
查看版本:
python --version
python -m pip --version查看解释器路径:
python -c "import sys; print(sys.executable)"查看包搜索路径:
python -c "import sys; print('\n'.join(sys.path))"Windows 上如果安装了多个版本,可以使用:
py -0
py -3.11 --version
py -3.12 --version排查环境问题时,最重要的不是看命令有没有成功,而是看“当前命令到底用了哪个解释器”。
虚拟环境解决什么问题
假设两个项目依赖同一个库的不同版本:
| 项目 | 依赖 |
|---|---|
| 旧后台系统 | fastapi==0.95.0 |
| 新 AI 服务 | fastapi==0.115.0 |
如果都装在全局环境,后安装的版本可能覆盖前面的版本,导致旧项目突然不能运行。
虚拟环境就是给每个项目创建一套独立依赖目录。
flowchart TD
A["全局 Python"] --> B["项目 A .venv"]
A --> C["项目 B .venv"]
B --> D["fastapi 0.95"]
C --> E["fastapi 0.115"]注意:虚拟环境通常不会复制一整个 Python,它会引用或链接基础解释器,再创建独立的可执行入口和依赖目录。
创建虚拟环境
在项目根目录执行:
python -m venv .venv推荐命名为 .venv,原因:
- IDE 容易识别。
- 放在项目根目录方便定位。
.gitignore很容易排除。
激活虚拟环境:
# Windows PowerShell
.venv\Scripts\Activate.ps1
# Windows cmd
.venv\Scripts\activate.bat
# macOS / Linux
source .venv/bin/activate退出虚拟环境:
deactivate激活后再检查:
python -c "import sys; print(sys.executable)"
python -m pip --version如果路径里出现当前项目的 .venv,说明环境正确。
Windows PowerShell 激活失败
如果 PowerShell 提示脚本执行策略禁止,可能会看到类似错误:
cannot be loaded because running scripts is disabled on this system可以对当前用户放开执行策略:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser然后重新激活:
.venv\Scripts\Activate.ps1这不是 Python 错误,而是 Windows PowerShell 的安全策略。
pip 常用命令
# 安装依赖
python -m pip install requests
# 安装指定版本
python -m pip install fastapi==0.115.0
# 升级包
python -m pip install -U requests
# 查看已安装包
python -m pip list
# 查看某个包详情
python -m pip show requests
# 导出依赖
python -m pip freeze > requirements.txt
# 安装依赖文件
python -m pip install -r requirements.txtpip list 和 pip freeze 的区别:
| 命令 | 适合用途 |
|---|---|
pip list | 人看当前装了什么 |
pip freeze | 生成可复现依赖清单 |
requirements.txt
requirements.txt 用于记录项目依赖,便于别人复现环境。
fastapi==0.115.0
uvicorn==0.30.6
requests==2.32.3别人拿到项目后:
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt为什么要锁版本?
如果只写:
fastapi
requests今天安装和三个月后安装可能得到不同版本。新版本可能改行为、删 API、改依赖,导致项目突然跑不起来。
依赖复现流程:
flowchart TD
A["开发者安装依赖"] --> B["确认项目能运行"]
B --> C["pip freeze 导出 requirements.txt"]
C --> D["提交代码仓库"]
D --> E["同事或服务器创建 .venv"]
E --> F["pip install -r requirements.txt"]
F --> G["得到相同依赖版本"]requirements 的局限
requirements.txt 简单直接,但有几个局限:
- 不区分直接依赖和间接依赖。
- 不天然区分开发依赖和生产依赖。
- 没有统一的项目元信息。
- 依赖冲突时不如现代工具清晰。
小脚本、简单项目用它足够。中大型项目可以考虑 pyproject.toml。
pyproject.toml 是什么
pyproject.toml 是 Python 现代项目配置文件,常用于描述项目元信息、依赖、构建工具、格式化工具、类型检查工具配置。
示例:
[project]
name = "asset-api"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"fastapi==0.115.0",
"uvicorn==0.30.6",
"requests==2.32.3",
]
[tool.pytest.ini_options]
testpaths = ["tests"]常见工具:
| 工具 | 特点 |
|---|---|
| pip + venv | 标准、简单、通用 |
| Poetry | 项目管理完整,依赖解析和 lock 文件成熟 |
| PDM | 基于现代标准,适合包管理 |
| uv | 速度很快,适合新项目和 CI |
| conda | 科学计算、AI、CUDA、二进制依赖场景常见 |
不要为了“看起来高级”强行上复杂工具。团队已有规范就按团队规范;没有规范时,小项目 venv + requirements.txt 就够用。
依赖冲突是怎么来的
依赖冲突通常不是你直接装的两个包冲突,而是它们的间接依赖冲突。
flowchart TD
A["你的项目"] --> B["Package A"]
A --> C["Package B"]
B --> D["common-lib >=1.0,<2.0"]
C --> E["common-lib >=2.0,<3.0"]
D --> F{"版本范围是否有交集"}
E --> F
F -->|没有| G["依赖解析失败"]排查命令:
python -m pip check
python -m pip show 包名解决思路:
- 先确认业务是否真的需要两个冲突包。
- 查看包的兼容版本范围。
- 升级或降级其中一个包。
- 必要时更换库或拆分服务。
- 不要盲目
pip install -U,否则可能引入更多变化。
import 路径和包结构
项目结构示例:
asset_api/
app/
__init__.py
main.py
services/
__init__.py
asset_service.py
requirements.txt运行时,Python 会根据 sys.path 查找模块。常见错误:
ModuleNotFoundError: No module named 'app'可能原因:
- 当前工作目录不在项目根目录。
- 没有激活虚拟环境。
- 包结构缺少
__init__.py。 - IDE 配置的解释器不是项目
.venv。 - 用了相对导入,但运行方式不对。
推荐从项目根目录运行:
python -m app.main而不是随便进入某个子目录后运行脚本。
商业 Demo:从零创建 FastAPI 项目环境
创建目录:
mkdir asset-api
cd asset-api
python -m venv .venv激活环境:
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS / Linux
source .venv/bin/activate安装依赖:
python -m pip install fastapi==0.115.0 uvicorn==0.30.6
python -m pip freeze > requirements.txt创建 main.py:
from fastapi import FastAPI
app = FastAPI(title="asset-api")
@app.get("/health")
def health():
return {"status": "UP"}启动:
uvicorn main:app --reload验证:
http://127.0.0.1:8000/health
http://127.0.0.1:8000/docs交给同事时,只需要提交:
main.py
requirements.txt
.gitignore不要提交:
.venv/
__pycache__/
.pytest_cache/AI 项目环境为什么更容易炸
AI 项目通常涉及 Python、PyTorch、CUDA、显卡驱动、操作系统动态库。任何一层不匹配都可能失败。
flowchart TD
A["显卡驱动"] --> B["CUDA 运行时"]
B --> C["PyTorch 对应 CUDA 版本"]
C --> D["Python 版本"]
D --> E["Transformers / Embedding / LLM 依赖"]常见问题:
| 现象 | 可能原因 |
|---|---|
torch.cuda.is_available() 是 False | 驱动、CUDA、PyTorch 版本不匹配 |
| 安装 PyTorch 很慢 | 下载源慢或包很大 |
ImportError: DLL load failed | Windows 动态库缺失或版本不兼容 |
| 向量库安装失败 | 需要编译工具或特定 Python 版本 |
| 同事能跑自己不能跑 | Python、小版本依赖、系统库不同 |
AI 项目建议:
- 明确 Python 版本,例如
3.10。 - 明确 PyTorch 安装命令,不要只写
pip install torch。 - 记录 CUDA 版本和显卡驱动要求。
- 优先使用 lock 文件或容器镜像复现环境。
- 把模型文件、向量库数据和代码依赖分开管理。
Docker 和虚拟环境的关系
Docker 不是替代虚拟环境的同一个概念。
| 能力 | venv | Docker |
|---|---|---|
| 隔离 Python 包 | 可以 | 可以 |
| 隔离操作系统依赖 | 不可以 | 可以 |
| 复现部署环境 | 一般 | 更强 |
| 启动成本 | 低 | 较高 |
| 适合场景 | 本地开发 | 部署、CI、复杂依赖 |
很多团队会这样组合:
- 本地开发用
.venv。 - 提交
requirements.txt或pyproject.toml。 - CI 和生产用 Docker 构建镜像。
这样既保持本地开发轻量,又保证部署环境可复现。
常见问题排查
包安装成功但 import 失败
按这个顺序查:
flowchart TD
A["import 失败"] --> B["查看 python 路径"]
B --> C["查看 pip 路径"]
C --> D{"是否同一个 .venv"}
D -->|否| E["激活正确虚拟环境或用 python -m pip"]
D -->|是| F["pip show 包名"]
F --> G{"包是否真的安装"}
G -->|否| H["安装到当前环境"]
G -->|是| I["检查模块名是否和包名不同"]例如包名是 beautifulsoup4,导入名是:
from bs4 import BeautifulSoup包名和导入名不总是一致。
pip 安装到了错误的 Python
使用:
python -m pip --version
python -c "import sys; print(sys.executable)"确认两个路径都在当前项目 .venv 下。
requirements 安装失败
排查:
- Python 版本是否满足依赖要求。
- 操作系统是否支持该包。
- 是否需要 C/C++ 编译工具。
- 是否下载源不可用。
- 是否有版本冲突。
可以尝试:
python -m pip install -r requirements.txt -i https://pypi.org/simple
python -m pip check虚拟环境要不要提交
不要提交 .venv。原因:
- 体积大。
- 包含本机绝对路径。
- 跨系统不可复用。
- 会污染仓库。
提交依赖清单即可。
.gitignore 示例
.venv/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
.ruff_cache/
.env注意:.env 里经常有数据库密码、Token、模型 Key,不要提交。
开发建议
- 每个项目单独创建虚拟环境。
- 优先使用
python -m pip,避免 pip 指向错误环境。 - 依赖变更后及时更新依赖文件。
- 不要把
.venv、缓存、密钥提交到仓库。 - 项目 README 写清 Python 版本、启动命令、依赖安装命令。
- AI 项目额外记录 CUDA、PyTorch、模型文件位置。
- 生产部署尽量使用容器或自动化脚本,避免手工在服务器上补包。
面试标准回答
Python 虚拟环境解决什么问题?
标准回答:虚拟环境为每个项目创建独立的依赖目录,避免不同项目依赖版本互相污染。例如旧项目需要 FastAPI 0.95,新项目需要 FastAPI 0.115,如果都装全局环境就可能冲突。虚拟环境能让每个项目使用自己的解释器入口和 site-packages。
为什么推荐 python -m pip?
标准回答:因为 pip 可能指向另一个 Python 解释器,尤其是多版本 Python 或虚拟环境没激活时。python -m pip 表示使用当前这个 python 对应的 pip,可以减少包安装到错误环境的问题。
requirements.txt 有什么作用?
标准回答:它记录项目依赖及版本,别人或服务器可以通过 pip install -r requirements.txt 复现环境。锁定版本能减少由于依赖升级导致的不可预期问题。
pyproject.toml 和 requirements.txt 有什么区别?
标准回答:requirements.txt 更像依赖安装清单,简单直接;pyproject.toml 是现代 Python 项目配置文件,可以描述项目元信息、依赖、构建系统和工具配置,更适合中大型项目和包发布。
包安装了但 import 失败怎么查?
标准回答:先查当前运行的 python 路径和 python -m pip --version 是否属于同一个虚拟环境;再用 pip show 确认包是否安装;然后检查包名和导入名是否一致,以及当前工作目录和模块路径是否正确。
关联知识点
- Python 基础语法:理解解释器如何执行脚本。
- Python 函数与模块:理解导入机制、模块拆分和循环导入。
- Python Web API 开发:用 FastAPI 项目验证环境配置。
- Python 与 AI 开发:理解 AI 项目中 Python、CUDA、模型依赖的复杂性。
- DevOps Docker:理解容器如何复现部署环境。
