Python 脚本先用 compileall 检查语法,不必逐个运行

53 次浏览5 条回复

有一批 Python 文件只想快速确认语法没问题时,可以先跑 compileall,它不会执行模块里的业务代码。

环境:Python 3.11+。建个最小例子:

mkdir compile-demo && cd compile-demo
printf 'value = 1\n' > good.py
printf 'if True print(1)\n' > bad.py
python -m compileall -q .

命令会报出 bad.py 的语法位置;修好后再跑一次,安静退出就表示这批文件都能编译。CI 里可以对源码目录执行,适合做很轻量的提交前检查。它只看语法,导入依赖、类型和运行时错误还是得交给测试。

文件多的时候还可以加 -j 0,让 compileall 自动用多核并行:python -m compileall -q -j 0 src/。另外它会生成 __pycache__,本地只想临时检查的话,跑完记得确认这些目录已被 .gitignore 忽略。

如果只想把它当 CI 门禁,目标目录最好写得窄一点,比如 python -m compileall -q src tests,别从仓库根目录扫进去虚拟环境或生成目录。命令失败时会返回非零状态,CI 直接沿用这个退出码就行;通过时通常没有输出。

Zoe_JayLv1#2

如果只想把它当 CI 门禁,目标目录最好写得窄一点,比如 python -m compileall -q src tests,别从仓库根目录扫进去虚拟环境或生成目录。命令失败时会返回非零状态,CI 直接沿用这个退出码就行;通过时通常没有输出。

如果 CI 工作区不想留下 __pycache__,可以把字节码缓存集中到临时目录:PYTHONPYCACHEPREFIX="$PWD/.cache/pyc" python -m compileall -q src tests。这样仍然沿用退出码做门禁,生成物也不会散落在源码目录里;临时目录记得在 CI 结束时清理或加入缓存策略。

如果仓库里有少量必须跳过的生成目录,也可以用 -x 排除路径正则,比如:python -m compileall -q -x '(^|/)(build|dist|[.]venv)/' src tests。

不过这个正则是匹配文件路径的,建议先在本地故意放一个坏文件确认它确实会被扫到;别把排除规则写太宽,不然 CI 看起来通过了,其实关键目录没检查。

Nathan03Lv1#4

如果仓库里有少量必须跳过的生成目录,也可以用 -x 排除路径正则,比如:python -m compileall -q -x '(^|/)(build|dist|[.]venv)/' src tests。

不过这个正则是匹配文件路径的,建议先在本地故意放一个坏文件确认它确实会被扫到;别把排除规则写太宽,不然 CI 看起来通过了,其实关键目录没检查。

如果 CI 还会缓存或比较生成的 .pyc,可以考虑显式指定校验模式:python -m compileall -q --invalidation-mode checked-hash src。它不依赖源码文件的修改时间来判断是否失效,跨机器或缓存复用时更稳定;只是会改变生成字节码的元数据,没这个需求就不用特意加。