Python解释器启动流程
理解解释器启动流程有助于深入掌握Python运行机制和进行性能优化。
启动阶段概览
Python
python script.py
↓
1. 程序入口(main函数)
↓
2. 解释器初始化(Py_Initialize)
↓
3. 模块搜索路径设置(sys.path)
↓
4. 运行主模块(site, runpy等)
↓
5. 执行用户脚本
↓
6. 清理退出(Py_Finalize)
初始化阶段
Python
# 查看解释器信息
import sys
import sysconfig
print(f"版本: {sys.version}")
print(f"可执行文件: {sys.executable}")
print(f"平台: {sys.platform}")
print(f"字节序: {sys.byteorder}")
print(f"最大整数: {sys.maxsize}")
# 安装配置
print(f"安装路径: {sys.prefix}")
print(f"配置: {sysconfig.get_config_vars()}")
模块搜索路径
Python
import sys
# sys.path 的构建过程
print("模块搜索路径:")
for i, p in enumerate(sys.path):
print(f" {i}: {p}")
# 路径来源:
# 1. 脚本所在目录(或当前目录)
# 2. PYTHONPATH 环境变量
# 3. 标准库目录
# 4. site-packages
# 5. .pth 文件添加的路径
Python
# site 模块在初始化时被自动导入
import site
print(f"site-packages: {site.getsitepackages()}")
print(f"用户 site-packages: {site.getusersitepackages()}")
# 禁用 site 模块:python -S script.py
# 此时 sys.path 不包含 site-packages
启动钩子
Python
# sitecustomize.py - 放在 site-packages 中
# 在 site 模块导入时自动执行
import sys
print("sitecustomize.py executed")
# usercustomize.py - 用户级自定义
# 启用方式:python -s script.py 或设置 PYTHONNOUSERSITE=1
Python
# 启动时的编码设置
import sys
import locale
print(f"文件系统编码: {sys.getfilesystemencoding()}")
print(f"默认编码: {sys.getdefaultencoding()}")
print(f"区域编码: {locale.getpreferredencoding()}")
模块加载顺序
Python
# 查看已加载模块
import sys
print("启动时已加载模块:")
for name in sorted(sys.modules.keys()):
if not name.startswith('_'):
print(f" {name}")
# 内置模块(builtins, sys, _warnings等)在初始化时加载
# 标准库按需加载
# 第三方库按需加载
执行模式
Python
import sys
# 不同启动模式的 sys.flags
print("解释器标志:")
print(f" 优化级别: {sys.flags.optimize}")
print(f" 调试模式: {sys.flags.debug}")
print(f" 交互模式: {sys.flags.interactive}")
print(f" 检查模式: {sys.flags.inspect}")
# 命令行参数
print(f"参数: {sys.argv}")
print(f"原始参数: {sys.orig_argv}")
启动模式对比:
| 命令 | 模式 | 说明 |
|---|---|---|
python script.py | 脚本模式 | 执行脚本后退出 |
python -c "code" | 命令模式 | 执行命令后退出 |
python -m module | 模块模式 | 作为模块运行 |
python | 交互模式 | 进入REPL |
python -i script.py | 检查模式 | 执行后进入REPL |
主模块检测
Python
import sys
# __name__ 的值
# - 被直接执行: '__main__'
# - 被导入: 模块名
if __name__ == '__main__':
print("直接执行")
print(f"主模块: {sys.modules['__main__']}")
else:
print("被导入")
Python
# 获取主模块信息
import sys
import __main__
print(f"主模块文件: {__main__.__file__ if hasattr(__main__, '__file__') else 'N/A'}")
print(f"主模块名: {__main__.__name__}")
importlib 与模块执行
Python
# runpy 模块实现模块执行
import runpy
# 等同于 python -m module
result = runpy.run_module('json', run_name='__main__')
# 等同于 python script.py
result = runpy.run_path('script.py', run_name='__main__')
# 返回模块的全局命名空间
print(result.keys())
字节码缓存
text
# .pyc 文件的生成与使用
import py_compile
import importlib.util
# 手动编译
py_compile.compile('example.py', optimize=0)
# __pycache__ 目录
import sys
import os
cache_dir = os.path.join(os.path.dirname(__file__), '__pycache__')
print(f"缓存目录: {cache_dir}")
# 缓存失效条件
# 1. 源文件修改时间变化
# 2. 源文件大小变化
# 3. Python版本变化
# 4. 使用 -B 禁用缓存
要点总结
- 初始化完成解释器环境、sys模块、builtins的设置
- **
sys.path**由脚本目录、PYTHONPATH、标准库、site-packages组成 site模块负责添加第三方库路径和执行启动钩子- **
__name__**区分主模块与被导入模块 - 字节码缓存加速后续加载,可通过
-B禁用
📝 发现内容有误?点击此处直接编辑