本系列将会陆续整理分享一些的Python内置函数。
-
通过百度网盘获取:
链接:https://pan.baidu.com/s/11x9_wCZ3yiYOe5nVcRk2CQ?pwd=mnsj
提取码:mnsj
-
前往GitHub获取:
https://github.com/returu/Python_built-in_functions
exec(source, /, globals=None, locals=None, *, closure=None)
-
source
:必需参数,可以是字符串或代码对象。如果是字符串,它会被当作Python代码执行;如果是代码对象,通常是通过compile()函数生成的; -
globals:可选参数,指定一个字典,表示全局命名空间。如果省略或为None,则默认使用当前环境的全局命名空间。如果globals字典中没有包含键__builtins__,则会插入对内置模块builtins的引用。这允许执行的代码访问内置函数和变量。可以通过在globals中提供自定义的__builtins__字典,来控制执行代码可以访问哪些内置函数。 -
locals:可选参数,指定一个字典,表示局部命名空间。如果省略或为None,则默认使用globals参数指定的字典。如果globals也未指定,则使用当前环境的局部命名空间; -
closure:Pyhon 3.11版本新增的参数。当代码对象包含自由变量(即不是函数局部变量但又不是全局变量的变量)时,closure参数用于用于传递闭包变量。closure必须是一个元组,与代码对象的co_freevars属性长度完全匹配。
下面是一些使用 exec() 函数的示例:
-
示例 1:基本使用
code = """
def greet(name):
return f'Hello, {name}!'
print(greet('Alice'))
"""
exec(code) # 输出:Hello, Alice!
-
示例 2:全局和局部命名空间
若不指定globals和locals,代码会在当前作用域执行,可能修改当前变量。
x = 1
exec("x = 42")
print(x) # 输出 42(直接修改了当前作用域的 x)
通过传递自定义字典,限制代码的变量访问,隔离作用域。
# 通过传递自定义字典,限制代码的变量访问,隔离作用域
x = 1
# 定义全局变量
global_vars = {'x': 10, 'y': 10}
# 定义局部变量
local_vars = {'y': 20}
# 执行代码
exec("z = x + y", global_vars , local_vars)
print(local_vars['z']) # 输出 30
print(x) # 输出1(原始作用域的 x 不受影响)
在实际使用中,建议通过限制 globals 和 locals 隔离代码,在沙箱环境中控制闭包变量的访问(例如限制敏感数据)。
restricted_env = {
'__builtins__': {}, # 禁用内置函数
'safe_api': some_safe_function # 仅暴露安全接口
}
exec(user_code, restricted_env)
-
示例 3:限制内置函数
默认情况下,exec 会自动将 __builtins__ 插入 globals 字典,提供对内置函数(如 open, eval)的访问,可通过自定义 globals 禁用内置函数:
g = {'__builtins__': {}} # 空字典禁用所有内置函数
exec('print("test")', g) # 报错:NameError(print 未定义)
-
示例 4:使用代码对象
如果传递的是代码对象,通常是通过 compile() 函数生成的。
code = """
x = 5
y = 10
print(f"x + y = {x + y}")
"""
# 结合compile()预编译代码,模式应为'exec'或'single'
compiled_code = compile(code, "<string>", "exec")
exec(compiled_code) # 输出:x + y = 15
-
示例 5:使用 closure 参数
closure
参数是Python 3.11新增的,用于支持闭包变量的显式传递。
# 定义一个外部函数,生成闭包环境
def outer(x):
# inner 函数引用外部变量 x(形成闭包)
def inner():
return x # 闭包变量 x
return inner
# 生成闭包函数并提取闭包信息
closure_func = outer(42)
# 获取 inner 函数的代码对象
code_obj = closure_func.__code__
# 获取闭包变量元组
# closure_func.__closure__ 获取闭包中的 cell 对象(包含变量 x 的值)
closure = closure_func.__closure__
# 修改闭包变量的值
closure[0].cell_contents = 100
# 动态执行代码对象并传递闭包
exec(code_obj, # 要执行的代码对象(inner 的函数体)
{"__builtins__": __builtins__}, # globals全局变量
{}, # locals局部变量
closure=closure # 通过关键字参数显式传递闭包变量
)
# 由于exec()不会返回函数对象,直接调用closure_func来验证闭包变量是否被修改
print(closure_func()) # 输出: 100
在Python 3.11之前的版本中,无法直接通过exec()传递闭包变量。若需动态生成闭包函数,可以使用types.FunctionType手动绑定闭包。
import types
def outer(x):
def inner():
return x
return inner
# 生成闭包函数并提取闭包信息
closure_func = outer(42)
code_obj = closure_func.__code__
closure = closure_func.__closure__
# 修改闭包变量的值
closure[0].cell_contents = 100
# 手动创建函数对象并绑定闭包
dynamic_inner = types.FunctionType(
code_obj,
globals={"__builtins__": __builtins__}, # 全局变量
closure=closure # 直接绑定闭包
)
print(dynamic_inner()) # 输出: 100


本篇文章来源于微信公众号: 码农设计师