先聊一个很常见的场景:你写了一个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 参数强制覆盖就行。

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

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

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

pipreqs ./src ./apps --force

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

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

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

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

真正容易让 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删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。