如何在 Python 中执行包含 Python 代码的字符串?
对于语句,请使用 exec(string)
(Python 2/3) 或 exec string
(Python 2):
>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world
当您需要表达式的值时,请使用 eval(string)
:
>>> x = eval("2+2")
>>> x
4
但是,第一步应该是问问自己是否真的需要。执行代码通常应该是不得已的位置:如果它可以包含用户输入的代码,它会变得缓慢、丑陋和危险。您应该始终首先查看替代方案,例如高阶函数,看看它们是否能更好地满足您的需求。
在示例中,使用 exec 函数将字符串作为代码执行。
import sys
import StringIO
# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()
code = """
def f(x):
x = x + 1
return x
print 'This is my output.'
"""
# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
exec code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
print f(4)
s = codeErr.getvalue()
print "error:\n%s\n" % s
s = codeOut.getvalue()
print "output:\n%s" % s
codeOut.close()
codeErr.close()
exec
(除非您知道代码字符串来自受信任的来源)。
eval
和 exec
是正确的解决方案,它们可以以更安全的方式使用。
如 Python's reference manual 中所述并在 this 教程中明确解释,eval
和 exec
函数采用两个额外参数,允许用户指定可用的全局和局部函数和变量。
例如:
public_variable = 10
private_variable = 2
def public_function():
return "public information"
def private_function():
return "super sensitive information"
# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len
>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12
>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined
>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters
>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined
本质上,您正在定义将在其中执行代码的命名空间。
eval
或 exec
打算用作 exec(input("Type what you want"))
?在很多情况下,程序可能会根据计算结果编写过程或函数。生成的函数将与编写良好的程序的任何其他部分一样安全和快速(一旦评估)。 包含 exec
的不安全程序并不比不安全程序本身造成的损害更危险,因为 exec
不会赋予程序任何新的特权。
请记住,从版本 3 开始,exec
是一个函数!
因此请始终使用 exec(mystring)
而不是 exec mystring
。
避免执行和评估
在 Python 中使用 exec 和 eval 是非常不受欢迎的。
有更好的选择
从最佳答案(强调我的):
对于语句,请使用 exec。当您需要表达式的值时,请使用 eval。但是,第一步应该是问问自己是否真的需要。执行代码通常应该是不得已的位置:如果它可以包含用户输入的代码,它会变得缓慢、丑陋和危险。您应该始终首先查看替代方案,例如高阶函数,看看它们是否能更好地满足您的需求。
使用字符串中的名称设置和获取变量的值 [虽然 eval] 可以工作,但通常不建议使用对程序本身有意义的变量名称。相反,最好使用字典。
这不是惯用语
来自 http://lucumr.pocoo.org/2011/2/1/exec-in-python/(强调我的)
Python 不是 PHP 不要试图绕过 Python 习语,因为其他一些语言的做法不同。命名空间出现在 Python 中是有原因的,仅仅因为它为您提供了工具 exec,并不意味着您应该使用该工具。
有危险
来自 http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html(强调我的)
所以 eval 是不安全的,即使你删除了所有的全局变量和内置函数!所有这些保护 eval() 的尝试的问题在于它们是黑名单。他们明确地删除了可能是危险的东西。这是一场失败的战斗,因为如果列表中只剩下一个项目,您就可以攻击系统。那么,可以使 eval 安全吗?很难说。在这一点上,我最好的猜测是,如果你不能使用任何双下划线,你就不会造成任何伤害,所以如果你排除任何带有双下划线的字符串,你是安全的。也许...
很难阅读和理解
来自 http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html(强调我的):
首先, exec 使人类更难阅读您的代码。为了弄清楚发生了什么,我不仅要阅读你的代码,我还必须阅读你的代码,弄清楚它将生成什么字符串,然后阅读那个虚拟代码。所以,如果你在一个团队中工作,或者发布开源软件,或者在 StackOverflow 之类的地方寻求帮助,你会让其他人更难帮助你。而且,如果您有任何机会在 6 个月后调试或扩展此代码,那么您将直接让自己变得更加困难。
cfg.yaml
) 导入相对路径:reldir : ../my/dir/
和 reldir = cfg[reldir]
。但是,由于这个 python 代码应该在 Windows 和 Linux 上运行,我需要它来适应不同的操作系统路径分隔符; \\
或 /
。所以我在配置文件中使用了 reldir : os.path.join('..','my','dir')
。但这只会导致 reldir
成为这个文字字符串,而不是被评估,所以我无法在 reldir
中打开文件。你有什么建议吗?
eval()
仅用于表达式,而 eval('x+1')
有效,例如 eval('x=1')
无效。在这种情况下,最好使用 exec
,甚至更好:尝试找到更好的解决方案 :)
值得一提的是,'exec
的兄弟存在,如果你想调用一个 python 文件,它也被称为 execfile
。如果您正在使用包含糟糕 IDE 的第三方包并且您想在其包之外进行编码,这有时会很好。
例子:
execfile('/path/to/source.py)'
或者:
exec(open("/path/to/source.py").read())
您可以使用 exec 完成代码的执行,如以下 IDLE 会话:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
正如其他人提到的,它是“执行” ..
但是,如果您的代码包含变量,您可以使用“全局”来访问它,也可以防止编译器引发以下错误:
NameError:名称“p_variable”未定义
exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
我尝试了很多东西,但唯一有效的是以下内容:
temp_dict = {}
exec("temp_dict['val'] = 10")
print(temp_dict['val'])
输出:
10
好的..我知道这不完全是一个答案,但可能是给像我一样看这个的人的注释。我想为不同的用户/客户执行特定的代码,但也想避免 exec/eval。我最初希望为每个用户将代码存储在数据库中并执行上述操作。
我最终在“customer_filters”文件夹中的文件系统上创建文件并使用“imp”模块,如果没有为该客户应用过滤器,它就会继续
import imp
def get_customer_module(customerName='default', name='filter'):
lm = None
try:
module_name = customerName+"_"+name;
m = imp.find_module(module_name, ['customer_filters'])
lm = imp.load_module(module_name, m[0], m[1], m[2])
except:
''
#ignore, if no module is found,
return lm
m = get_customer_module(customerName, "filter")
if m is not None:
m.apply_address_filter(myobj)
所以 customerName = "jj" 将从 customer_filters\jj_filter.py 文件中执行 apply_address_filter
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
等,然后他们可以将其写为exec ("x.%s = 42" % s)
。对于这种常见情况(您只需要访问存储在字符串中的对象的属性),有一个更快、更清晰、更安全的函数getattr
:只需写getattr(x, s) = 42
来表示相同的意思。setattr(x, s, 42)
吗?我尝试了getattr(x, 2) = 42
,但以can't assign to function call: <string>, line 1
失败setattr(x, s, 42)
是正确的语法。令人惊讶的是花了这么长时间才发现这个错误。无论如何,关键是getattr
和setattr
是exec
的替代品,当您想要获取任意成员时,通过字符串查找。