推荐使用 importlib.import_module() 动态导入模块,它语义清晰、支持相对导入和包层级;__import__() 不推荐,行为反直觉且易错;从文件路径加载适用于插件等特殊场景,但需手动管理模块缓存。

Python 动态导入模块,核心是绕过 import 语句的静态特性,在运行时按需加载模块。关键不在于“能不能”,而在于“用哪种方式更安全、可控、可维护”。
使用 importlib.import_module()(推荐)
这是官方推荐的标准方式,语义清晰、支持相对导入、能处理包层级,且与静态 import 行为一致。
- 导入顶层模块:
importlib.import_module('json') - 导入子模块:
importlib.import_module('xml.etree.ElementTree') - 从包中相对导入(需指定
package参数):importlib.import_module('.utils', package='myproject.api') - 导入后建议缓存模块对象,避免重复导入开销
使用 __import__()(不推荐,仅作了解)
这是 import 语句底层调用的函数,但行为反直觉(例如对点号分隔的模块名默认只返回最外层包),容易出错。
-
__import__('os.path')返回的是os模块,不是os.path - 要获取子模块需额外操作:
getattr(__import__('os.path'), 'path')—— 易错且难读 - 缺乏对相对导入的明确支持,已逐步被
importlib取代
从文件路径直接加载(适用于插件或热重载场景)
当模块不在 sys.path 中,或需要从任意 .py 文件加载时,可用 importlib.util.spec_from_file_location + importlib.util.module_from_spec。
立即学习“Python免费学习笔记(深入)”;
- 先构造 spec:
spec = importlib.util.spec_from_file_location('mymodule', '/path/to/mymodule.py') - 再创建并执行模块:
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module) - 注意:该方式绕过 Python 的模块缓存机制,多次调用会生成多个独立模块对象,需手动管理
- 适合配置驱动的插件系统、Jupyter 环境中的动态代码执行等有限场景
常见陷阱与注意事项
动态导入不是“万能胶”,用错地方反而引入隐蔽问题。
-
异常处理必须到位:模块不存在、语法错误、导入时抛异常都会触发
ImportError或ModuleNotFoundError,不捕获会导致程序中断 - 避免硬编码模块名字符串:应通过配置、用户输入或约定目录结构生成模块路径,增强可维护性
-
慎用
eval()或exec()拼接 import 语句:存在严重安全风险,且破坏可读性和调试能力 - 考虑替代方案:如功能简单,用工厂函数+字典映射可能比动态导入更轻量、更易测试










