← [ BACK_TO_NOTES ]

Python 导入系统

import 由 finders/loaders 完成定位与执行,结果缓存于 sys.modules;可扩展但应谨慎。

#concept #growing #dev #python #python

[!info] related notes

Python 导入系统

这个概念为什么出现

插件系统、命名空间包、延迟加载都碰到导入钩子。理解 finders/loaders 与缓存,才能诊断“导入到错误文件/循环/未刷新”。

[!abstract] 一句话理解 导入先查 sys.modules;未命中时通常通过 finder/loader 创建模块,先放入缓存再执行代码,以支持循环导入。自定义 hook 可扩展,但增加调试成本。

最小可观察示例

场景:查看已缓存模块与查找路径

# import_system_observe.py
# 业务意图:观察 sys.modules 与 sys.path 入口。
# 教学点:缓存与搜索路径。

import sys
import json


def main() -> None:
    print("json cached?", "json" in sys.modules)
    print("path0:", sys.path[0])
    print("json file:", getattr(json, "__file__", None))


if __name__ == "__main__":
    main()

建议运行:

python import_system_observe.py

期望输出:json cached? True 与路径信息。

结合场景再看三个关注点

  1. 标准库导入后即缓存。
  2. 此脚本模式下 sys.path[0] 通常是脚本目录;-m、-c、交互模式及 -P/-I 等安全选项会改变初始搜索路径。
  3. 改 path 是权宜之计。

核心概念与准确模型

  1. sys.modules 按模块全名缓存;未命中才进入 finder 查找。
  2. finder 返回 module spec,loader 创建模块(或用默认创建)。
  3. 模块先写入 sys.modules,再由 exec_module 执行;执行失败会移除失败模块,已成功加载的依赖通常仍留在缓存。
  4. 子模块搜索使用父包 path;namespace package 不要求 init.py。

边界情况与反直觉行为

  1. 删除 sys.modules 再导入可产生另一个模块对象,旧引用不会自动更新;reload 也不会更新外部 from-import 已绑定的名字。
  2. 循环导入 半初始化
  3. zipimport 等特殊 finder

常见误区

[!warning] 常见误区:import 只是文本包含 错误理解:C 的 #include。
正确模型:执行并缓存模块对象。

工程实践

  • 应用用包导入
  • 插件入口用明确注册
  • 少写自定义 import hook

本节总结

导入系统是可扩展运行时子系统。日常够用“包+绝对导入”,进阶才碰 hook。

自测题

  1. sys.modules 作用?
  2. 循环导入常见修复?
参考答案
  1. 缓存模块对象;普通重复导入复用它。reload、删缓存和用另一模块名加载不属于这个保证。
  2. 重划依赖、延迟导入、把共享类型下沉。

延伸阅读与资料来源

资料类型支撑内容
The import system规范全文
importlib文档API
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本