Python项目依赖管理:requirements文件全解析

8 次阅读

Python项目中的第三方库数量一旦增加,手动记录依赖版本很容易造成环境不一致。开发机器能够正常运行,换一台电脑却出现模块缺失、版本冲突,甚至部署到服务器后直接启动失败,很多时候都与依赖管理不规范有关。

requirements文件正是Python项目中最常见的依赖管理方式之一。通过它可以集中记录项目运行所需要的第三方包及版本信息,并结合pip快速完成依赖安装、环境迁移和部署。

一、什么是requirements文件

requirements文件通常命名为requirements.txt,本质上是一个纯文本文件,用于描述Python项目依赖的第三方软件包。

一个简单的requirements.txt可能如下:

Django==5.1.2
requests==2.32.3
PyYAML==6.0.2
pandas>=2.2.0

每一行通常对应一个依赖包,也可以指定版本约束。

例如:

requests==2.32.3

表示安装指定版本。

requests>=2.32.3

表示安装不低于2.32.3的版本。

requests<3.0

表示版本必须低于3.0。

也可以同时指定上下限:

requests>=2.30.0,<3.0.0

这种方式能够在版本兼容性和依赖更新之间取得一定平衡。

需要注意的是,requirements.txt并不是Python语言强制规定的文件格式,而是Python生态中约定俗成的一种依赖描述方式。pip能够读取该文件,并根据其中的内容安装依赖。

二、requirements.txt的主要作用

项目使用requirements文件,核心目的并不是简单保存几个包名,而是让项目运行环境具备可复现性。

1. 快速搭建开发环境

拿到一个新的Python项目后,可以直接执行:

Bash
pip install -r requirements.txt

pip会读取文件中的依赖,并自动安装。

相比逐个执行:

Bash
pip install requests
pip install pandas
pip install flask

统一管理更加方便。

2. 保持不同环境的一致性

项目通常会经历开发、测试和生产等多个环境。

如果每个环境自行安装依赖,很容易出现:

开发环境:requests 2.32.3
测试环境:requests 2.31.0
生产环境:requests 2.28.2

某些API或行为发生变化后,就可能出现“本地正常、服务器异常”的问题。

通过requirements文件可以降低这种环境差异。

3. 方便项目部署

服务器部署Python项目时,通常只需要准备Python运行环境,然后执行:

Bash
pip install -r requirements.txt

就能够完成大部分项目依赖安装。

4. 方便团队协作

团队成员从Git仓库获取项目后,可以根据requirements文件快速恢复项目依赖,而不需要询问项目开发者“这个项目还需要安装哪些库”。

三、requirements文件常见版本写法

理解版本约束,是正确维护requirements文件的关键。

固定版本

Flask==3.0.3

表示严格安装3.0.3。

固定版本适合对运行环境稳定性要求较高的项目,尤其是生产环境。

大于等于某个版本

requests>=2.31.0

表示允许安装2.31.0及以上版本。

这种写法比较灵活,但如果未来发布的新版本存在兼容性变化,也可能给项目带来风险。

小于某个版本

numpy<3.0

表示版本必须低于3.0。

指定版本范围

Django>=4.2,<5.0

表示允许4.2及以上,但不能达到5.0。

不等于某个版本

urllib3!=2.0.0

表示排除2.0.0版本。

多条件组合

requests>=2.30,<3.0

能够同时限制最低和最高版本。

四、如何生成requirements.txt

已有Python项目时,最常见的方法是使用pip freeze。

首先查看当前环境中的已安装包:

Bash
pip freeze

可能得到:

Django==5.1.2
PyYAML==6.0.2
requests==2.32.3
urllib3==2.2.3

将结果保存到文件:

Bash
pip freeze > requirements.txt

执行完成后,当前目录下就会生成:

requirements.txt

之后可以查看:

Bash
cat requirements.txt

Windows环境则可以直接打开该文件查看。

五、pip freeze并不一定等于项目真正需要的依赖

这是实际开发中非常容易忽略的问题。

假设一个虚拟环境中安装了:

Django
requests
pytest
black
jupyter
numpy
pandas

但项目代码实际上只使用:

Django
requests

执行:

Bash
pip freeze > requirements.txt

之后,所有安装在当前环境中的包都可能被写入文件。

这会造成requirements.txt越来越庞大,并且混入测试工具、格式化工具以及其他与项目运行无关的包。

因此,pip freeze更准确地说是“记录当前环境”,而不是自动分析“项目实际依赖”。

对于小型项目,可以使用它快速生成依赖清单;对于大型项目,则建议结合虚拟环境、依赖分组或专门的依赖管理工具进行维护。

六、requirements.txt如何安装依赖

拿到项目后,进入项目根目录:

Bash
cd myproject

执行:

Bash
pip install -r requirements.txt

如果系统中存在多个Python版本,更推荐:

Bash
python -m pip install -r requirements.txt

Linux环境也经常使用:

Bash
python3 -m pip install -r requirements.txt

这种方式可以减少pip与Python解释器对应错误的问题。

例如系统同时存在Python 3.10和Python 3.12时:

Bash
pip install requests

不一定能够明确对应你当前使用的Python环境。

而:

Bash
python3.12 -m pip install requests

则明确使用Python 3.12对应的pip。

七、结合虚拟环境使用requirements

Python项目推荐使用虚拟环境,而不是直接向系统Python安装大量项目依赖。

创建虚拟环境:

Bash
python -m venv .venv

Windows激活:

Bash
.venvScriptsctivate

Linux或macOS激活:

Bash
source .venv/bin/activate

激活后安装依赖:

Bash
python -m pip install -r requirements.txt

完成后,可以检查:

Bash
pip list

这样项目之间的依赖就能够相互隔离。

例如:

项目A
└── .venv
    └── Django 4.2

项目B
└── .venv
    └── Django 5.1

两个项目可以使用不同版本的Django,而不会互相影响。

八、requirements文件中的注释和路径依赖

requirements文件不仅可以记录普通PyPI包,也支持注释。

例如:

# Web framework
Django==5.1.2

# HTTP client
requests==2.32.3

以#开头的内容通常作为注释处理。

还可以安装Git仓库中的项目,例如:

git+https://github.com/example/project.git

也可以指定分支:

git+https://github.com/example/project.git@develop

如果项目依赖本地目录,也可以使用类似:

-e ./my_package

-e表示以editable模式安装,适合项目开发阶段使用。

九、requirements.txt中如何处理不同环境

实际项目经常存在开发环境和生产环境依赖不同的问题。

例如生产环境只需要:

Django==5.1.2
gunicorn==23.0.0
psycopg==3.2.3

开发环境还需要:

pytest
black
ruff
ipython

一种常见的组织方式是拆分文件:

requirements/
├── base.txt
├── development.txt
└── production.txt

base.txt:

Django==5.1.2
requests==2.32.3

development.txt:

-r base.txt

pytest
black
ruff

production.txt:

-r base.txt

gunicorn
psycopg

开发环境执行:

Bash
pip install -r requirements/development.txt

生产环境执行:

Bash
pip install -r requirements/production.txt

这样能够避免把开发工具安装到生产服务器。

十、requirements.in与requirements.txt有什么区别

部分Python项目会同时出现:

requirements.in
requirements.txt

两者用途并不完全相同。

requirements.in通常用于记录项目直接依赖,例如:

Django
requests
pandas

而requirements.txt可以进一步记录经过解析后的完整依赖及版本,例如:

Django==5.1.2
asgiref==3.8.1
sqlparse==0.5.1
requests==2.32.3
urllib3==2.2.3
certifi==2024.8.30

前者强调“项目直接需要什么”,后者更偏向“最终环境安装什么”。

这种模式通常会配合pip-tools使用,通过依赖解析生成锁定版本的requirements文件。

例如:

Bash
pip-compile requirements.in

然后得到:

requirements.txt

安装时:

Bash
pip-sync requirements.txt

对于需要较强环境可复现能力的项目,这种方式比单纯维护一个巨大的pip freeze结果更加清晰。

十一、requirements.txt如何升级依赖

升级某个指定包,可以直接执行:

Bash
pip install --upgrade requests

然后查看当前版本:

Bash
pip show requests

如果项目使用pip freeze维护requirements,可以重新生成:

Bash
pip freeze > requirements.txt

不过重新生成前应该确认当前虚拟环境中没有安装大量与项目无关的软件包,否则可能把不需要的依赖一起写进去。

如果只想更新requirements中的某一个依赖,也可以手动修改:

requests==2.32.3

改为:

requests==2.33.0

然后重新执行:

Bash
pip install -r requirements.txt

十二、如何检查requirements依赖是否存在冲突

安装依赖后,可以执行:

Bash
pip check

如果没有问题,通常会显示:

No broken requirements found.

如果存在依赖冲突,则会提示具体的软件包和版本要求。

例如某个库要求:

urllib3<2

而当前环境却安装了:

urllib3 2.2.3

就可能导致兼容性问题。

出现这种情况时,不应该简单地强制安装某个版本,而应该检查依赖链,确认哪个软件包提出了版本限制。

还可以使用:

Bash
pip show package_name

查看具体包的信息。

十三、requirements.txt常见错误

1. 找不到requirements.txt

执行:

Bash
pip install -r requirements.txt

如果出现文件不存在,通常是当前目录不正确。

可以先执行:

Bash
ls

Linux/macOS查看目录内容,Windows可以使用:

cmd
dir

确认requirements文件实际位置。

如果文件位于config目录:

Bash
pip install -r config/requirements.txt

2. Could not find a version that satisfies the requirement

例如:

ERROR: Could not find a version that satisfies the requirement xxx

可能原因包括:

  • 包名称写错;

  • Python版本不兼容;

  • 当前平台没有对应的预编译包;

  • 指定的版本已经不存在或不可用;

  • pip版本过旧;

  • 使用了无法访问的软件源。

可以先升级pip:

Bash
python -m pip install --upgrade pip

然后重新安装。

3. Permission denied

如果直接向系统Python安装依赖,可能遇到权限错误。

更推荐创建虚拟环境:

Bash
python -m venv .venv

然后在虚拟环境中执行:

Bash
python -m pip install -r requirements.txt

而不是长期依赖:

Bash
sudo pip install -r requirements.txt

4. 版本冲突

例如requirements中同时出现:

packageA==1.0
packageB==2.0

而packageB依赖:

packageA>=2.0

就会产生无法满足的版本要求。

此时需要重新检查直接依赖和间接依赖,而不是盲目删除某一行。

十四、requirements.txt的最佳实践

使用虚拟环境

每个项目建立独立环境:

Bash
python -m venv .venv

避免多个项目共用系统Python环境。

生产项目尽量锁定版本

例如:

Django==5.1.2
requests==2.32.3

生产环境对稳定性要求较高,固定版本能够减少自动升级带来的不确定性。

开发和生产依赖分离

测试工具、代码格式化工具、调试工具没有必要全部进入生产环境。

可以采用:

requirements/base.txt
requirements/development.txt
requirements/production.txt

进行管理。

定期更新依赖

依赖长期不更新,可能积累安全漏洞和兼容性问题。

但升级时不要直接一次性更新所有软件包。更稳妥的方式是逐项升级、运行测试,再确认是否需要修改代码。

将requirements文件纳入版本控制

如果项目使用Git,应将:

requirements.txt

或者对应的requirements目录提交到代码仓库。

同时通常不需要提交:

.venv/

可以在.gitignore中添加:

.venv/
venv/
__pycache__/

十五、requirements.txt与pyproject.toml的关系

现代Python项目越来越多地使用pyproject.toml管理项目元数据和依赖。

例如:

TOML
[project]
name = "demo-project"
version = "1.0.0"
dependencies = [
    "requests>=2.32",
    "Django>=5.1"
]

相比传统的requirements.txt,pyproject.toml能够承载更多项目级配置,包括项目名称、版本、构建系统以及依赖声明等。

不过,这并不意味着requirements.txt已经失去作用。

两种方式的定位并不完全相同:

文件主要用途
requirements.txt描述环境安装依赖
requirements.in描述直接依赖并用于生成锁定文件
pyproject.tomlPython项目元数据、依赖及构建配置
uv.lock等锁定文件记录更精确的解析结果

对于传统项目,requirements.txt依然简单、直观、兼容性好;对于新项目,则可以根据团队技术栈选择pyproject.toml以及相应的现代依赖管理工具。

十六、一个实用的requirements管理流程

一个相对规范的Python项目依赖管理流程可以归纳为:

创建虚拟环境
    ↓
安装项目需要的第三方库
    ↓
开发并测试项目
    ↓
整理直接依赖
    ↓
固定或约束关键版本
    ↓
生成requirements文件
    ↓
提交Git仓库
    ↓
其他环境创建虚拟环境
    ↓
pip install -r requirements.txt
    ↓
运行pip check和项目测试

如果项目规模较小,可以直接维护:

requirements.txt

项目规模扩大后,可以进一步采用:

requirements/
├── base.txt
├── development.txt
└── production.txt

或者:

requirements.in
requirements.txt

通过分层管理降低依赖维护成本。

十七、一个完整示例

假设项目目录如下:

my-project/
├── app/
│   ├── __init__.py
│   └── main.py
├── requirements.txt
├── .gitignore
└── README.md

requirements.txt内容:

Flask==3.0.3
requests==2.32.3
python-dotenv==1.0.1

新环境中执行:

Bash
python -m venv .venv

激活虚拟环境后:

Bash
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

检查依赖:

Bash
python -m pip check

查看安装结果:

Bash
python -m pip list

项目就可以在相对一致的Python环境中运行。

如果后续修改了依赖,应同步更新requirements文件,并通过Git提交变更,确保其他开发人员和部署环境使用相同的依赖描述。

对于Python项目而言,requirements文件解决的并不是“怎么安装一个库”这样简单的问题,而是如何让项目依赖清晰、可追踪、可复现。合理使用版本约束、虚拟环境、依赖分层和依赖检查,可以显著减少环境差异导致的问题。对于小型项目,规范维护requirements.txt已经足够;随着项目规模扩大,则可以逐步引入requirements.in、依赖锁定工具或pyproject.toml,建立更加完善的Python项目依赖管理体系。