Python 内置函数 compile 的用法详解
4 回复
Eval(open(xx.py).Read())
compile() 是用来把字符串代码编译成字节码对象的内置函数,主要用在动态执行代码的场景。它有三个参数:source(代码字符串)、filename(文件名标识)、mode(编译模式)。
三种模式:
'exec':编译模块级代码,返回的代码对象可以用exec()执行'eval':编译单个表达式,返回的代码对象可以用eval()执行并返回结果'single':交互式单条语句,类似 Python shell
基本用法:
# exec 模式 - 执行多行代码
code_str = """
x = 10
y = 20
print(f'Sum: {x + y}')
"""
compiled = compile(code_str, '<string>', 'exec')
exec(compiled) # 输出: Sum: 30
# eval 模式 - 计算表达式
expr = "3 * 4 + 5"
compiled = compile(expr, '<string>', 'eval')
result = eval(compiled) # result = 17
# single 模式 - 交互式语句
single_code = "print('Hello, World!')"
compiled = compile(single_code, '<string>', 'single')
exec(compiled) # 输出: Hello, World!
实际应用场景:
- 动态代码执行:从配置文件或数据库读取代码逻辑
user_logic = "result = [i**2 for i in range(5)]"
compiled = compile(user_logic, '<user_code>', 'exec')
namespace = {}
exec(compiled, namespace)
print(namespace['result']) # [0, 1, 4, 9, 16]
- 表达式计算器:
def safe_calculator(expression, variables=None):
"""安全计算数学表达式"""
if variables is None:
variables = {}
try:
compiled = compile(expression, '<calc>', 'eval')
return eval(compiled, {"__builtins__": {}}, variables)
except Exception as e:
return f"Error: {e}"
# 使用示例
result = safe_calculator("a + b * 2", {'a': 5, 'b': 3})
print(result) # 11
- 模板引擎简化版:
template = "Welcome {name}, your score is {score:.2f}"
context = {'name': 'Alice', 'score': 95.5}
# 动态生成格式化代码
code = f"f'{template}'"
compiled = compile(code, '<template>', 'eval')
result = eval(compiled, {}, context)
print(result) # Welcome Alice, your score is 95.50
重要细节:
filename参数只是标识符,可以是任意字符串,但在错误跟踪中会显示- 编译后的代码对象可以重复使用,提高多次执行的性能
- 使用
compile()+exec()比直接exec()字符串更高效,特别是重复执行时 - 安全警告:永远不要编译执行不可信的代码,这有严重的安全风险
性能对比:
import timeit
code_to_repeat = "sum(i**2 for i in range(1000))"
# 直接 exec
t1 = timeit.timeit(lambda: exec(code_to_repeat), number=1000)
# 先编译再执行
compiled = compile(code_to_repeat, '<test>', 'exec')
t2 = timeit.timeit(lambda: exec(compiled), number=1000)
print(f"Direct exec: {t1:.4f}s")
print(f"Compiled then exec: {t2:.4f}s")
# 通常编译后执行快 2-5 倍
简单说就是:需要动态执行代码时用 compile(),但要注意安全。
with open(‘xx.py’, ‘r’) as f:
obj = compile(f.read(), ‘’, ‘exec’)
exec(obj)
import xx
e = compile(’’, ‘xx.py’, ‘exec’)
exec(e)

