如何在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()
eval
并且exec
是正确的解决方案,它们可以更安全的方式使用.
正如Python的参考手册中所讨论并在本教程中清楚地解释的那样,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 "", line 1, in File " ", line 1, in 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 " ", line 1, in File " ", line 1, in NameError: name 'private_function' is not defined
实际上,您正在定义将在其中执行代码的命名空间.
请记住,版本3 exec
是一个功能!
所以总是用exec(mystring)
而不是exec mystring
.
eval()
仅仅是表达式,而eval('x+1')
作品,eval('x=1')
不会起作用.在这种情况下,最好使用exec
,甚至更好:尝试找到更好的解决方案:)
exec
和eval
exec
和eval
非常不受欢迎.从最顶层的答案(强调我的):
对于陈述,请使用
exec
.当您需要表达式的值时,请使用
eval
.但是,第一步应该是问问自己是否真的需要.执行代码通常应该是最后的手段:如果它可以包含用户输入的代码,那么它是缓慢,丑陋和危险的.您应该首先查看备选方案,例如更高阶的功能,看看它们是否能更好地满足您的需求.
从替代品到执行/评估?
使用字符串中的名称设置和获取变量的值
[while
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个月后调试或扩展这段代码,你就会直接让自己变得更难.
您使用exec完成执行代码,如以下IDLE会话:
>>> kw = {} >>> exec( "ret = 4" ) in kw >>> kw['ret'] 4
使用eval。