f-string不能用于动态导入模块,必须用importlib.import_module();它接收字符串参数,支持f-string拼接合法模块路径,行为明确且官方推荐,而__import__()易返回顶层包导致错误。

f-string 不能用于动态导入模块
直接用 f-string 拼接模块名并执行 import 是无效的——Python 的 import 语句在编译期解析,不接受运行时拼接的字符串。写类似 import {module_name} 这种代码会触发 SyntaxError,因为 import 不是函数,无法被 f-string“注入”。
动态导入必须用 importlib.import_module()
真正可行的方式是借助 importlib 模块,它专为运行时导入设计。关键点在于:importlib.import_module() 接收的是字符串,不是语法结构,所以你可以安全地用 f-string 构造模块路径:
例如,想根据变量 pkg 和 sub 导入 requests.api:
import importlib
<p>pkg = "requests"
sub = "api"
module = importlib.import_module(f"{pkg}.{sub}") # ✅ 正确
</p>
-
f"{pkg}.{sub}"只是生成字符串"requests.api",传给函数,不触碰语法层 - 模块路径必须是合法的、可解析的完整名称(如
"os.path",不能只写"path") - 若模块不在
sys.path中,会抛出ModuleNotFoundError,需提前确保路径正确或捕获异常
常见错误:混淆 __import__() 和 importlib.import_module()
__import__() 虽然也能动态导入,但行为反直觉——它默认返回的是**顶层包**,不是你写的那个子模块。比如 __import__("requests.api") 返回的是 requests 对象,而非 requests.api。这极易引发 AttributeError。
相比之下,importlib.import_module() 行为明确、符合直觉,且是官方推荐方式:
-
importlib.import_module("a.b.c")→ 返回a.b.c模块对象 -
__import__("a.b.c", fromlist=[""])才等价,但写法冗长易错 - 如果模块名来自用户输入或配置文件,务必对字符串做基本校验(如是否含非法字符、是否为空),避免注入风险
导入后如何安全使用变量名?
动态导入得到的模块对象是普通 Python 对象,你可以赋值给任意变量名,但注意这不会影响全局命名空间中的模块缓存——importlib 内部仍按完整路径缓存。例如:
mod = importlib.import_module("json")
# 此时 mod 就是 json 模块,可用 mod.dumps(),但 json 名字本身未自动引入
- 不要试图用
exec()或eval()来“让名字进作用域”,那既危险又不可靠 - 如果需要多个模块统一处理,建议用字典管理:
modules = {"json": importlib.import_module("json"), ...} - 重复调用
importlib.import_module()同一模块不会重复加载,它会复用sys.modules中已有的缓存
实际中最容易忽略的是模块路径的合法性判断和异常处理——f-string 只负责拼字符串,不保证这个字符串能对应真实模块。一旦拼错或路径不存在,程序就停在 ModuleNotFoundError,没有 fallback。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











