oneliner: 扫描python 仓库 import 信息
收集整个仓库的import信息
前置管道逻辑是: find 命令寻找所有 *.py 文件 | 用 grep -v 过滤包含EXCLUDE 的文件 | 对每个文件, 提取包含 import 的行 | 删除行首的 leading whitespace
find ./ -name "*.py" |grep -v EXCLUDE | xargs grep -h "import" | sed 's/[ \t]*//' > imports
到这一步, 输出是这样:
接下来针对不同的import 语句提取包的名字。
提取package 列表
针对不同的 python 的导入语句处理上一步的结果, 得到完整的包列表。
整包导入:import xx,yy
导入1个包: import package1
导入N个包: import package1, package2, package3
cat imports |egrep "^import" | sed 's/import[ \t]\+//' |awk -F"," '{for(i=1;i<=NF;i++)print $i}' |sed 's/^[ \t]\+//' | awk '{print $1}' | awk -F"." '{print $1}' |sort -u
行首匹配 import | 移除 import 及后面的whitespace | 一次导入N个包则每个包输出一行,如果只有1个包则原样输出 | 删除输出造成的leading white space | 如果有 import A as B 仅输出 A | 如果有 import A.B 仅输出 A | 排序去重
看起来是这样
部分导入:from A.B import xx, yy
选择部分导入: from package.x import A,B,C
cat imports| egrep "^from" | sed 's/from[ \t]\+//' | awk '{print $1}' | awk -F"." '{print $1}' |sort -u
行首匹配 from | 移除 from 及后面的whitespace | 拿到包的名字 | 如果有 A.B 仅输出 A | 排序去重
看起来是这样:
总结
运行速度非常快,秒级
awk -F"," '{print $1}' 的默认行为很有意思,如果该行不包含 "," , 会把整行输出, 这个默认行为让代码简单了很多
不能处理跨行的 import。 多数情况下不是问题, 比如我做这个需求是为了收集信息写 requirements.txt , 如果个别遗漏,执行冒烟报错, 少量修改即可添加完整。
管道中很多逻辑是处理white spaces 的,看起来很罗嗦但是对异常覆盖的很好, 原因不多说
有没有现成的轮子? 有! 但是都假设你在某个特定的 virtualenv 下, pip 或者 conda 会维护当前虚拟环境的包信息
pip3 freeze > requirements.txt
conda list -e > requirements.txt
- 点赞
- 收藏
- 关注作者
评论(0)