Python 中如何根据名字(或路径)动态导入模块?
Python 动态导入模块用 importlib.import_module("模块名");按文件路径导入用 importlib.util.spec_from_file_location。本文介绍各种动态导入方式。
按模块名动态导入用 importlib.import_module("itertools")——等价于 import itertools,但模块名可以是字符串变量。按文件路径导入用 importlib.util.spec_from_file_location 系列函数。
按模块名导入
import importlib
itertools = importlib.import_module('itertools')
# 等价于 import itertools,但名字可以是运行时确定的字符串
# 导入子模块
json = importlib.import_module('os.path')
检查模块能否导入(不实际导入)
import importlib.util
spec = importlib.util.find_spec('itertools')
if spec is not None:
print("可以导入")
按文件路径导入
import importlib.util
import sys
spec = importlib.util.spec_from_file_location("my_module", "/path/to/my_module.py")
module = importlib.util.module_from_spec(spec)
sys.modules["my_module"] = module
spec.loader.exec_module(module)
适合插件系统——从任意目录加载 .py 文件作为模块。
典型场景:插件加载
# 加载 plugins/ 目录下所有 .py 文件作为插件
import importlib
import pkgutil
import plugins
for _, name, _ in pkgutil.iter_modules(plugins.__path__):
module = importlib.import_module(f'plugins.{name}')
module.register() # 调用插件的注册函数
常见问题(FAQ)
Q:import() 和 importlib.import_module() 有什么区别?
A:__import__ 是底层函数,对带点的名字返回顶层包而非子模块,行为反直觉;import_module 是官方推荐的高层接口。
Q:动态导入的模块能热更新吗?
A:用 importlib.reload(module) 可以重新加载已导入的模块,但已有的类实例不会自动更新,生产环境慎用。
Q:导入失败怎么处理?
A:包一层 try/except ImportError,插件场景下某个插件加载失败不应影响主程序。