
1. 项目缘起为什么我们需要一个requirements.txt如果你写过Python项目尤其是和别人协作过或者尝试过在不同机器上运行同一个项目那你大概率遇到过这个场景在自己电脑上跑得好好的代码换台机器或者发给同事一运行就报错满屏的ModuleNotFoundError。问题往往出在依赖上——你安装了pandas1.5.3而对方的环境里可能是pandas2.0.0或者干脆没装。这种“在我这能跑”的困境是Python项目协作和部署中最常见也最令人头疼的问题之一。requirements.txt文件就是解决这个问题的“项目依赖说明书”。它不是一个Python语法文件而是一个纯文本文件里面按行记录了你项目运行所必需的所有第三方库及其精确版本。有了它其他人包括未来的你就能通过一条简单的命令一键复现出与你完全一致的Python运行环境从根本上杜绝因依赖不一致导致的各类诡异Bug。这个看似简单的文本文件其背后关联着Python生态的核心工作流虚拟环境隔离、依赖解析、版本锁定和持续集成。无论是个人脚本、数据分析项目还是大型Web应用规范地管理requirements.txt都是迈向专业开发的第一步。接下来我将结合多年踩坑经验从零开始彻底讲清楚如何生成、使用和优化这个文件让你告别环境配置的烦恼。2. 环境基石为什么必须先有虚拟环境在谈论生成requirements.txt之前有一个更前置、更关键的概念必须厘清虚拟环境Virtual Environment。很多新手会直接在全局Python环境中安装包然后导出依赖这是一个巨大的误区。想象一下你的电脑是一个大厨房全局Python环境。你先后做了三个项目项目A需要番茄酱版本1.0项目B需要番茄酱版本2.0项目C需要一种特殊的、项目A和B都不兼容的辣椒酱。如果你把所有调料都堆在厨房中央的大桌子上很快你就会发现为了做项目C你升级了辣椒酱结果导致项目A完全做不出来了因为辣椒酱的新版本改变了味道。更糟的是你根本记不清每个项目到底用了哪些调料的具体版本。虚拟环境就是为每个项目单独准备的“料理台”。每个料理台都有自己独立的调料架site-packages目录互不干扰。你在“项目A的料理台”上安装番茄酱1.0在“项目B的料理台”上安装番茄酱2.0它们和平共处。requirements.txt记录的就是某个特定料理台上所有调料的清单。创建虚拟环境是第一步且必须在安装任何项目依赖之前进行。常见的虚拟环境工具有venv (Python 3.3 内置)轻量、无需额外安装是大多数场景的首选。virtualenv第三方工具比venv功能更丰富一些但在Python 3.3之后venv已足够好用。Conda更强大的环境管理工具尤其擅长处理包含非Python依赖如C库的科学计算环境。这里以最通用的venv为例。打开你的终端Windows用CMD或PowerShellmacOS/Linux用Terminal进入你的项目目录然后执行# 在当前目录下创建一个名为 venv 的虚拟环境文件夹 python -m venv venv这条命令做了几件事它调用Python的venv模块在当前目录创建了一个名为venv的文件夹。这个文件夹里包含了独立的Python解释器、pip工具以及一个空的site-packages目录。创建完成后你需要激活这个虚拟环境这样你的终端会话才会知道应该使用这个“料理台”而不是“大厨房”。Windows (CMD/PowerShell):# 在CMD中 venv\Scripts\activate.bat # 在PowerShell中可能需要先设置执行策略 venv\Scripts\Activate.ps1macOS / Linux:source venv/bin/activate激活后你的命令行提示符通常会发生变化前面会多出一个(venv)的标识这表示你已经进入了虚拟环境。此时你使用pip install安装的任何包都只会安装到这个独立的venv目录下完全不会影响系统或其他项目。注意一个常见的错误是创建了虚拟环境但没有激活结果安装的包还是到了全局环境。务必在安装依赖前确认命令行提示符中有(venv)字样。如果你在VSCode或PyCharm中开发这些IDE通常可以自动识别并为你激活项目目录下的虚拟环境但了解手动操作原理依然很重要。3. 依赖安装与记录pip的进阶用法虚拟环境激活后我们就可以开始安装项目依赖了。最直接的方式是使用pip install。但这里有几个层次直接决定了你未来requirements.txt的质量。3.1 基础安装与版本指定假设你的项目需要requests库来处理HTTP请求需要pandas来处理数据并且你知道pandas的2.0版本有一个你依赖的新特性而requests只要不是太老的版本就行。你可以这样安装pip install requests pip install pandas2.0.0pip install requests安装requests的最新稳定版。pip install pandas2.0.0精确安装pandas的2.0.0版本。3.2 从依赖文件安装更常见的场景是你拿到一个已有的项目里面已经有了requirements.txt。这时一键安装所有依赖的命令是pip install -r requirements.txt-r参数告诉pip去读取指定文件并安装文件中列出的所有包。这是团队协作和项目部署的标准操作。3.3 生成requirements.txtpip freeze的利与弊当你在这个虚拟环境中安装好了所有必需的包如何生成依赖清单呢最广为人知的命令是pip freeze requirements.txt这条命令会将当前虚拟环境中所有通过pip安装的包及其精确版本包括次级版本号和构建号输出到requirements.txt文件。例如certifi2023.7.22 charset-normalizer3.2.0 idna3.4 numpy1.24.3 pandas2.0.0 python-dateutil2.8.2 pytz2023.3 requests2.31.0 six1.16.0 tzdata2023.3 urllib32.0.4看起来完美对吗但它有一个致命缺陷它会导出环境里的所有包包括那些你间接依赖的、甚至是不必要的包。比如你只安装了pandas但pip freeze会把pandas所依赖的numpy、python-dateutil、pytz等全部列出来。这会导致你的依赖文件非常臃肿并且可能包含一些只在特定操作系统或架构下才需要的底层依赖当在其他环境安装时可能引发冲突。3.4 更优雅的选择pipreqs 或 pip-tools对于大多数项目我们更希望requirements.txt只包含我们直接安装的“顶层依赖”让pip自己去解决传递依赖。这时工具就派上用场了。pipreqs这个工具会扫描你的项目源代码.py文件自动找出所有import语句并生成对应的requirements.txt。它更贴近项目的真实直接依赖。# 首先安装pipreqs可以在全局环境安装因为它是个工具 pip install pipreqs # 然后在项目根目录运行 pipreqs . --encodingutf-8 --force--force参数会覆盖已有的requirements.txt。生成的文件可能只包含pandas和requests非常干净。但它有个小缺点如果某些库是通过动态导入或插件机制引入的它可能无法捕获。pip-tools这是一套更专业、更强大的工具链包含pip-compile和pip-sync。它的工作流是你维护一个requirements.in文件里面只写顶层依赖可以不加版本或写版本范围然后通过pip-compile命令生成一个锁定所有次级依赖精确版本的requirements.txt。# 安装 pip install pip-tools # 创建 requirements.in内容如 # pandas2.0 # requests # 编译生成requirements.txt pip-compile requirements.in生成的requirements.txt会包含所有传递依赖的精确版本并且会附上注释说明每个包是哪个顶层依赖带来的。当你想更新依赖时修改requirements.in再次运行pip-compile即可。pip-sync命令则用于严格同步环境它会安装requirements.txt中的所有包并卸载环境中多余的包确保环境绝对纯净。实操心得对于个人小项目或脚本pip freeze勉强够用。但对于任何正经的、可能需要协作或部署的项目我强烈推荐从开始就使用pip-tools。它虽然多了一步但带来了清晰的依赖分层.in文件表达意图.txt文件锁定环境和可重复的构建是工程化的体现。pipreqs则非常适合快速为一个已有项目生成干净的依赖清单。4. requirements.txt的语法详解与最佳实践一个requirements.txt文件不仅仅是包名的罗列它有一套灵活的语法来控制版本。4.1 版本操作符package1.2.3 精确匹配版本1.2.3。package1.2.3 安装大于等于1.2.3的任何版本。package1.2.3 安装大于1.2.3的任何版本。package1.2.3 安装小于等于1.2.3的任何版本。package1.2.3 安装小于1.2.3的任何版本。package~1.2.3 兼容性发布。安装任何1.2.3且1.3.0的版本。这对于允许bug修复和安全更新但不允许可能破坏API的次要版本更新非常有用。4.2 从版本控制库或本地安装你不仅可以指定PyPI上的包还可以直接从Git仓库、本地路径安装# 从GitHub安装可指定分支、标签或提交哈希 -e githttps://github.com/user/repo.gitmaster#eggpackage_name # 从本地目录安装常用于开发自己的库 -e /path/to/your/local/package-e代表“可编辑模式”editable安装后对本地源码的修改会直接反映到环境中非常适合库的开发阶段。4.3 环境区分与额外依赖一个成熟的项目通常会有多套依赖基础依赖项目运行必不可少的部分。开发依赖仅用于开发阶段如测试框架pytest、代码格式化工具black、代码检查工具flake8等。文档依赖用于构建文档如sphinx。可选依赖某些特定功能需要的依赖比如[gui]功能需要PyQt5。一种常见的做法是使用多个文件requirements.txt 生产环境核心依赖。requirements-dev.txt或dev-requirements.txt 开发依赖。requirements-test.txt 测试依赖。在requirements-dev.txt中第一行可以是-r requirements.txt表示包含所有生产依赖然后再列出开发专用的包。这样部署时只需安装requirements.txt开发时则安装requirements-dev.txt。4.4 使用索引镜像加速安装国内从PyPI官方源下载包可能很慢。我们可以在安装时通过-i参数指定镜像源也可以将其直接写在requirements.txt中虽然这不是标准做法但某些工具支持。更通用的做法是在pip的配置文件中设置全局镜像。创建或修改~/.pip/pip.confLinux/macOS或%APPDATA%\pip\pip.iniWindows[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple trusted-host pypi.tuna.tsinghua.edu.cn常用的国内镜像源有清华、阿里云、中科大等。设置后所有的pip install命令都会默认使用该镜像速度会有质的提升。避坑指南在requirements.txt中不要使用宽松的版本范围如numpy除非你确信所有版本都兼容。在生产环境中始终使用锁定精确版本或使用~锁定兼容版本这是保证环境一致性的生命线。版本冲突是Python依赖地狱的主要来源精确锁定能让你在已知的、测试过的版本上稳定运行。5. 高级工作流与Conda和现代打包工具的结合pip和requirements.txt是Python官方的标准但在数据科学和机器学习领域Conda占据了半壁江山。Conda不仅能管理Python包还能管理非Python的二进制依赖如CUDA、MKL数学库这对于配置复杂的科学计算环境至关重要。5.1 Conda环境与environment.ymlConda使用environment.yml文件来定义环境它比requirements.txt更强大。一个典型的environment.yml文件如下name: my-data-science-env # 环境名称 channels: - conda-forge - defaults dependencies: - python3.9 - numpy1.24 - pandas2.0 - scikit-learn - pip - pip: - requests2.31.0 # 对于某些PyPI特有或更新更快的包可以用pip安装创建环境的命令是conda env create -f environment.yml导出环境的命令是conda env export environment.yml。注意conda env export会导出非常详细的环境信息包括所有依赖和构建哈希通常用于完全重现。对于共享更推荐使用conda env export --from-history它只导出你显式安装的包。5.2 pip与Conda的混用策略最佳实践是优先使用Conda安装那些有复杂二进制依赖或Conda优化过的包如numpy, pandas, tensorflow-gpu等然后用pip安装Conda仓库中没有或版本滞后的纯Python包。就像上面的environment.yml示例所示在dependencies列表里先列出Conda包最后加上pip作为一个包然后在它下面缩进列出需要通过pip安装的包。这样可以最大程度保证环境的可复现性。5.3 现代打包标准pyproject.tomlPython社区正在从传统的setup.py和requirements.txt向pyproject.toml文件迁移。pyproject.toml是PEP 518引入的项目配置文件可以被pip、build、poetry、flit等现代工具识别。在这个文件里你可以定义项目的元数据、构建依赖以及可选依赖。对于应用项目而非库使用poetry或pdm这类工具可以更好地管理依赖和虚拟环境。它们会生成pyproject.toml和锁文件poetry.lock/pdm.lock能提供比pip更快的依赖解析和更可靠的依赖锁定。例如使用poetry初始化项目后添加依赖的命令是poetry add pandas它会自动更新pyproject.toml并解决依赖关系。经验之谈如果你是数据科学工作者面对CUDA、cuDNN等复杂环境Conda是无可替代的利器environment.yml是你的首选。如果你是纯Python Web后端或工具开发者正在启动一个新项目我建议你尝试一下poetry或pdm它们提供的依赖管理和打包体验比原始的pipvenv组合要流畅和现代得多。但对于维护已有项目或追求最大兼容性和简单性pip和requirements.txt依然是坚实可靠的基础。6. 实战排坑常见问题与解决方案在实际操作中你一定会遇到各种奇怪的问题。下面是一些高频坑点及其排查思路。6.1 “pip”不是内部或外部命令这是Windows新用户最常见的问题。错误信息是pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。原因Python或pip没有正确添加到系统环境变量PATH中。解决找到你的Python安装路径如C:\Users\YourName\AppData\Local\Programs\Python\Python39和Scripts子路径如...\Python39\Scripts。将这两个路径添加到系统的PATH环境变量中。更推荐的做法是在安装Python时务必勾选“Add Python to PATH”选项。如果已经安装可以运行Python安装程序选择“Modify”勾选该选项。6.2 安装超时或速度极慢原因网络连接PyPI官方服务器不稳定。解决如前所述永久配置国内镜像源是最佳方案。临时使用可以在安装命令后加-i参数如pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple。6.3 版本冲突错误信息通常为ERROR: Cannot install package-a1.0 and package-b2.0 because these package depend on conflicting versions of package-common.原因你试图安装的多个包对同一个底层依赖包要求了互不兼容的版本。解决这是最棘手的问题。首先尝试安装时不要一次性安装所有包先安装最核心、版本要求最严格的包。其次查看冲突的具体信息看能否找到同时满足所有要求的package-common的版本。如果不行可能需要寻找功能类似但依赖不同的替代库或者联系库的维护者。使用pip-tools可以在编译阶段就暴露出潜在的冲突。6.4 在虚拟环境中安装包失败提示权限不足原因虚拟环境激活失败或者在某些系统配置下pip仍然试图安装到需要管理员权限的全局目录。解决首先百分之百确认你的命令行提示符前有(venv)。如果没有请回到项目目录重新激活。其次永远不要使用sudo pip install在Linux/macOS上这会将包安装到系统全局环境破坏隔离性。如果虚拟环境权限确实有问题可以删除venv文件夹用python -m venv venv --without-pip先创建一个不带pip的环境然后手动安装pip。6.5 生成的requirements.txt在其他系统上安装失败原因可能包含了平台特定的二进制包如windows-curses或依赖了特定系统库。解决这就是为什么推荐使用pipreqs或手动维护顶层依赖而不是直接用pip freeze导出全部包。对于必须的、但有平台差异的依赖可以在requirements.txt中使用环境标记# 仅Windows需要 pywin32300; sys_platform win32 # 仅Linux需要 pyserial; sys_platform linuxpip在安装时会自动判断当前平台只安装符合条件的行。6.6 VSCode/PyCharm没有识别到虚拟环境原因IDE可能没有自动扫描到项目目录下的虚拟环境或者虚拟环境没有创建在标准位置。解决VSCode按下CtrlShiftP输入“Python: Select Interpreter”然后从列表中选择路径为./venv/Scripts/python.exeWindows或./venv/bin/pythonmacOS/Linux的解释器。PyCharm打开Settings/Preferences-Project: 项目名-Python Interpreter点击齿轮图标选择Add然后选择Existing environment指向你虚拟环境中的Python解释器。管理Python依赖是一项看似基础实则深刻的工作它直接关系到项目的可维护性、可协作性和可部署性。从手动管理到使用requirements.txt再到采用pip-tools、Conda或Poetry等现代工具反映了一个开发者工程化水平的提升。花时间搭建好这套基础设施未来在项目迁移、团队协作和线上部署时你会感谢当初那个“多事”的自己。记住一个干净、明确、可复现的依赖环境是任何成功Python项目的坚实起点。