python 3.9 与 3.10 的 import 机制无本质变更,差异仅体现在底层校验更严格:3.10 要求 modulespec.loader 非 none、提前检查 all 类型、强化类型注解中模块路径解析,影响自定义导入钩子、动态 all 和运行时类型反射场景。

Python 3.9 和 3.10 在包导入机制上**没有本质性变更**,官方未引入新的导入语法、协议或路径解析逻辑。所谓“差异”,实际集中在底层行为微调、错误提示优化及与新特性(如类型提示)的协同变化上,而非 import 本身的工作方式被重写。
import 语句本身没变,但 __import__ 和导入钩子的行为更严格
Python 3.10 对 importlib.util.spec_from_file_location 和 importlib.util.module_from_spec 的参数校验更严格,尤其当传入 None 作为 loader 或 origin 时,可能抛出 ValueError 而非静默忽略。这影响自定义导入钩子(MetaPathFinder 子类)的健壮性:
- 3.9 中部分宽松容忍的 spec 构造,在 3.10 下会直接失败
- 若你手动构造
ModuleSpec并传给importlib.util.module_from_spec,需确保spec.loader不为None,否则触发ImportError: missing loader - 第三方框架(如某些插件系统)若依赖旧式钩子写法,升级到 3.10 后需补全 loader 初始化逻辑
from ... import * 在 3.10 中对 __all__ 类型检查更早
当模块定义了 __all__ 但其值不是 list 或 tuple(比如是 set 或自定义迭代器),Python 3.9 通常在执行 from mod import * 时才报错;而 Python 3.10 会在模块首次被导入(即 import mod 阶段)就检查 __all__ 类型,提前抛出 TypeError: __all__ must be a list or tuple of strings。
- 这不是 bug,而是 PEP 626(精确行号)和导入流程重构带来的副作用
- 常见于动态生成
__all__的工具模块,例如用set(dir()) - {'__builtins__'}构建,需显式转成list() - 该检查仅影响
__all__声明本身,不影响正常from mod import name导入
类型提示中的模块引用在 3.10 下解析更严格
Python 3.10 默认启用 PEP 563(延迟求值注解),但同时强化了对字符串字面量中模块路径的解析逻辑。若你在类型注解里写 "mymodule.MyClass",而 mymodule 尚未被导入或路径不合法,3.10 可能在运行时(而非仅 mypy 静态检查时)触发 NameError 或 ImportError,尤其在使用 typing.get_type_hints() 时:
- 3.9 中这类错误常被忽略或延迟到实际实例化时才暴露
- 3.10 因解释器内部 AST 解析增强,更早捕获无效模块名引用
- 解决方案:确保字符串中模块名可被当前导入上下文解析,或改用
from __future__ import annotations+ 显式导入目标模块
真正容易被忽略的是:这些差异几乎不会在普通 import requests 场景中暴露,只在深度定制导入行为、动态模块加载、或强依赖运行时类型反射的场景下浮现。如果你的项目没碰过 importlib 钩子、没手写 __all__、也没用 get_type_hints 解析字符串注解,那 3.9 和 3.10 的 import 对你来说就是一回事。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











