如何基于/tmp/vendor目录还原Python进程依赖及版本生成requirements.txt
方案一:静态扫描方案(无需依赖运行中的进程,稳定性最高)
该方案完全基于pip安装包生成的标准文件实现,不会出现匹配错误问题:
- 第一步:扫描
/tmp/vendor目录下所有*.dist-info格式的目录,pip安装的所有合规包必然会生成该目录,目录内的METADATA文件存储了包的官方名称、版本等标准信息,RECORD文件存储了该包安装的所有文件的相对路径列表。 - 第二步:提取所有包的官方名称和版本,无需解析目录名(避免出现包名和模块名不一致、版本号带特殊字符导致解析错误的问题),可直接用以下shell命令提取全量包信息:
for dist_dir in /tmp/vendor/*.dist-info; do pkg_name=$(grep '^Name:' "${dist_dir}/METADATA" | awk '{print $2}') pkg_version=$(grep '^Version:' "${dist_dir}/METADATA" | awk '{print $2}') echo "${pkg_name}==${pkg_version}" done > all_installed_pkgs.txt
- 第三步:将你追踪到的所有
/tmp/vendor下的进程加载文件路径,和每个包的RECORD文件内的路径做匹配,只要进程加载的任意文件属于某个包的RECORD列表,就将该包纳入最终的requirements文件即可。
方案二:动态方案(仅用于静态扫描存在特殊情况的补充)
你之前动态导入拿不到版本是没用对标准接口,Python有官方稳定的版本获取方法:
- 第一步:从你追踪到的模块文件路径提取顶层模块名,比如
/tmp/vendor/requests/utils.py对应的顶层模块名为requests。 - 第二步:使用和目标进程完全相同版本的Python解释器执行以下代码,即可批量获取版本:
import sys # 优先加载/tmp/vendor下的模块,避免和系统环境的模块冲突 sys.path.insert(0, '/tmp/vendor') # Python3.8+用importlib.metadata,更低版本可替换为pkg_resources from importlib.metadata import version, PackageNotFoundError # 此处替换为你提取到的所有顶层第三方模块名集合 used_top_modules = {"requests", "certifi", "urllib3", "idna"} requirements = [] for mod_name in used_top_modules: try: ver = version(mod_name) requirements.append(f"{mod_name}=={ver}") except PackageNotFoundError: # 触发该异常说明模块不是通过pip安装的,通常是单文件自定义模块,直接拷贝文件即可无需写入requirements pass with open("requirements.txt", "w", encoding="utf-8") as f: f.write("\n".join(requirements))
注意事项
- 没有
.dist-info目录的模块都不是通过pip安装的,不需要写入requirements.txt,直接拷贝对应文件/目录到新环境的第三方库目录即可正常使用。 - 最终生成的requirements.txt完全兼容
pip install -r requirements.txt --target <安装目录>的安装方式。
内容的提问来源于stack exchange,提问作者vesii
相关产品推荐
相关产品推荐

