商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Python中Pipreqs自动生成项目依赖清单的实现

Python中Pipreqs自动生成项目依赖清单的实现

  发布于2026-07-12 阅读(0)

扫一扫,手机访问

先聊一个很常见的场景:你写了一个Python项目,准备部署到服务器或者交给同事,需要一份依赖清单。很多人第一反应是 pip freeze > requirements.txt,但这样做往往会埋下隐患。更可靠的做法,其实是换用 pipreqs

Python中Pipreqs自动生成项目依赖清单的实现

pipreqs 生成 requirements.txt 为什么比 pip freeze 更靠谱

简单来说,pipreqs 的核心理念就是——"只扫自己门前的雪"。它只盯着项目源码里那些实实在在用了 import 语句引入的包,绝不会把整个Python环境里装了一堆但你压根没用的包也塞进清单里。

pip freeze 则是典型的"一锅端"。它把当前虚拟环境(甚至全局环境)里所有已安装的包一股脑儿全导出来,不管这些包是项目真正需要的,还是你为了某个调试小工具临时装的。问题就出在这里:等你真正部署上线,或者把项目交接给同事时,经常会出现"这个包根本用不上却报错""那个必需的包又因为冲突卡住"的尴尬情况。这不是代码写错了,而是依赖清单里混了太多"无关人士"。

适用场景很清晰:新项目初始化、把代码交给别人、准备 Docker 镜像构建、提交代码前自查依赖。但也要注意,它不擅长处理那些纯粹的开发依赖,比如 pytestblack 这类工具——默认情况下是会被忽略的,除非你加了额外参数。另外,pipreqs 不解析 setup.pypyproject.toml,它的眼里只有 Python 源文件里实实在在写着的 import 语句。

安装和基础命令怎么跑起来

安装没什么复杂的,但有个细节值得留意:确保安装的是最新版,避免老版本那种路径相关的 bug。直接跑一句:

pip install --upgrade pipreqs

然后,进到你的项目根目录(就是 src/ 目录或者 app.py 等源码所在的那一层),执行:

pipreqs ./

它就会自动扫描目录下所有 .py 文件,然后生成一份清爽的 requirements.txt。如果运行时报错说找不到 requirements.txt,那是因为文件已存在,且被锁住了——删掉再跑一次,或者加个 --force 参数强制覆盖就行。

几个实用的小参数值得记住:

  • --encoding=utf-8:如果你的项目里夹杂了中文注释或路径,不加这个很可能会遇到 UnicodeDecodeError,加它就对了。
  • --diff requirements.txt:想增量更新?用它对比现有的依赖文件,只输出新增的包,适合在持续迭代中精细管理。
  • --sa vepath ./reqs-dev.txt:如果你不想覆盖主文件,比如想把开发依赖单独放一份,就用这个指定输出路径。

怎么让 pipreqs 扫描子目录和识别动态导入

默认情况下,pipreqs 只扫描当前目录及其直接的子目录。如果你的项目结构是 src/mylib/apps/api/ 这种多层嵌套,就可能漏掉关键依赖。这时候需要显式告诉它该去哪:

pipreqs ./src ./apps --force

但必须承认,pipreqs 在动态导入面前确实无能为力。比如你在代码里用了 __import__(f"{name}_plugin") 或者 importlib.import_module() 这样的字符串拼接式导入,它是完全"看不懂"的。这类依赖,只能老老实实手动补进 requirements.txt

一些常见的坑点再强调一下:

  • Django 项目里,你在 INSTALLED_APPS 中配置的第三方 app(比如 django-crispy-forms),pipreqs 并不会自动识别过去。为什么?因为它只认 import 语句,不解析配置文件。这类依赖必须你人工核对添加。
  • 如果你用了 setuptoolsentry_points 或插件机制,同样没戏。
  • 一个实用的建议:执行完 pipreqs 后,不妨再用 grep -r "import\|from.*import" . --include="*.py" 快速扫一遍,看看有没有可疑或遗漏的模块名。

生成结果不准?先检查 import 语句写法

pipreqs 的工作原理决定了它依赖的是"字面量"分析,而不是代码真正的运行时行为。所以某些写法会导致结果"对不上号":

  • 能识别的import requests as req 没问题,它会认出 requestsimport mypkg.utils 也能认出 mypkg。但要注意,它不会深挖 mypkg 内部又依赖了哪些包。
  • 没问题的:相对导入比如 from . import configfrom ..models import User,只是影响模块查找,不会引入新的第三方包,所以不会有问题。
  • 容易被误解的:像 try: import ujson except ImportError: import json 这种写法,pipreqs 会把 ujson 也识别为依赖,哪怕实际运行走的可能是 json。它不管运行时的逻辑分支,只认代码里写着的 import

真正容易让 pipreqs "失手"的,其实是那些条件导入加上第三方包的组合。举个例子:

if sys.version_info >= (3, 9):
    from importlib import resources
else:
    import importlib_resources as resources

这种情况下,pipreqs 会忠实地把 importlib_resources 也列进清单。但问题在于,如果你的运行环境已经是 Python 3.9 以上,importlib_resources 这个包根本不会生效。这时候就得你动动手指,把实际没用的那个依赖删掉。

本文转载于:https://www.jb51.net/python/362912u5o.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注