本文详解如何在 python 中将形如 `"x = 5"` 的字符串解析并执行为真实变量赋值,重点说明 `exec` 与 `eval` 的适用场景、局部/全局作用域限制,以及推荐的安全替代方案。
在 Python 中,直接通过字符串动态创建或修改变量(例如将 "X = 5" 转为 X = 5)看似简单,但受语言设计约束,其实现方式需谨慎选择——尤其要区分全局作用域与函数局部作用域。
在模块顶层(即全局作用域),exec() 是最直接有效的方案:
exec("X = 5")
print(X) # 输出: 5它等价于手动书写 X = 5,因为全局命名空间本质上是 globals() 返回的可变字典。你也可以用更精确的 compile 配合 exec:
exec(compile("X = 5", "", "single")) 其中 "single" 表示单条语句(适合赋值),而 "exec" 支持多行代码块。
在函数内部,无法通过 exec 或 eval 动态创建或修改真正的局部变量。原因在于:Python 在编译函数时已静态确定局部变量集合,locals() 返回的是一个只读快照(shallow copy),对其修改不会影响真实栈帧中的变量:
def bad_example():
x = 1
exec("x = 99") # ❌ 无效!x 仍为 1
print(x) # 输出: 1
bad_example()最佳实践是显式传入一个 dict 作为执行上下文,所有赋值均发生在此字典中,再从中提取结果:
def safe_assign(statement: str, initial_scope: dict = None) -> dict:
scope = initial_scope.copy() if initial_scope else {}
exec(statement, globals(), scope)
return scope
# 使用示例
result = safe_assign("X = 5; Y = 'hello'; Z = [1, 2, 3]")
print(result['
X']) # 5
print(result['Y']) # 'hello'
print(result['Z']) # [1, 2, 3]? 安全提示:exec 和 eval 执行任意字符串存在严重安全风险(如代码注入)。仅在完全信任输入来源时使用;生产环境建议改用 ast.literal_eval()(仅支持字面量)或专用解析器(如 pyparsing)处理结构化赋值。
掌握这一机制,既能满足动态脚本化需求,又能守住代码健壮性与安全性底线。