python script.py 按下回车到你的第一行代码执行之间,解释器做了什么?这篇不查资料——直接让 Python 自己汇报:用 -X importtime 看导入顺序,用 -S、-I 看开关的作用,再往 site-packages 里放一个 .pth 文件,亲眼看它在你的脚本之前执行。
python -X importtime -c pass 共 45 行导入记录, 其中最外层(不是被别的模块触发)的 7 个, 顺序如下 (自身耗时 µs / 累计 µs):
1. _frozen_importlib_external 自身 319 累计 564
2. zipimport 自身 121 累计 421
3. encodings 自身 333 累计 928
4. encodings.utf_8 自身 105 累计 105
5. _signal 自身 41 累计 41
6. site 自身 235 累计 5434
7. linecache 自身 149 累计 149
最外层累计耗时合计 ≈ 7642 µs
其中 site 模块(处理 site-packages / .pth / sitecustomize)一项累计 5434 µs一次空启动记录了 45 行导入(含被别的模块触发的),其中最外层只有 7 个:先是 _frozen_importlib_external(让 import 自己能工作)和 zipimport,再是 encodings/utf_8(文本编码),_signal,然后是 site——它一项就占 5434 µs,是最大的开销,最后 linecache。这些都发生在你的脚本之前。
python -c pass 18.8 ms 启动后 sys.modules 有 54 个 python -S -c pass (不 import site) 12.8 ms 启动后 sys.modules 有 21 个 python -I -c pass (隔离模式) 18.5 ms 启动后 sys.modules 有 54 个 python -I -S -c pass 12.9 ms 启动后 sys.modules 有 21 个 python -E -c pass (忽略环境变量) 18.9 ms 启动后 sys.modules 有 54 个
-S 让 site 不再导入:启动从 18.8 ms 降到 12.8 ms,启动后的 sys.modules 从 54 个降到 21 个。-I(隔离模式)几乎没有变快,模块数也没变——它并没有跳过 site,只是让 site 忽略环境变量和用户目录。-E 只忽略环境变量。想要「最小启动」需要 -S,想要「不受环境影响」用 -I,两者不是一回事。
在用户 site-packages 里放 demo.pth, 在 PYTHONPATH 里放 sitecustomize.py, 然后运行: [.pth] demo.pth 的这一行在启动时执行了 [sitecustomize] 被自动导入了 [脚本] 主脚本开始执行 extra_path 在 sys.path 里? True 同样的环境, 加 -S: [脚本] 主脚本开始执行 extra_path 在 sys.path 里? False 同样的环境, 加 -I: [脚本] 主脚本开始执行 extra_path 在 sys.path 里? False
我在用户 site-packages 里放了一个 demo.pth:一行以 import 开头(会被当作代码执行),一行是路径(会被加进 sys.path);在 PYTHONPATH 指定的目录里放了 sitecustomize.py。运行结果显示,它们都在「主脚本开始执行」之前打印,路径也确实进了 sys.path。加 -S 或 -I 后两者都没有执行。
site-packages 里的 *.pth 和 sitecustomize/usercustomize。 orig_argv = ['-I', '-c', 'import sys; print("orig_argv =", sys.orig_argv[1:], "| argv =", sys.argv, "| isolated =", sys.flags.isolated, "| no_user_site =", sys.flags.no_user_site, "| ignore_environment =", sys.flags.ignore_environment)'] | argv = ['-c'] | isolated = 1 | no_user_site = 1 | ignore_environment = 1sys.orig_argv 保留完整的原始命令行(包括给解释器的 -I、-c),sys.argv 只是交给脚本自己的那部分。-I 同时打开了 isolated、no_user_site、ignore_environment 三个标志。
-X importtime 的耗时随机器负载有波动,本次绝对值仅供参考-X frozen_modules)的影响、Windows 上的启动路径、编译成字节码缓存后的冷启动