如何在Python中执行包含Python代码的string?
如何在Python中执行包含Python代码的string?
对于语句,使用exec(string)
(Python 2/3)或exec string
(Python 2):
>>> mycode = 'print "hello world"' >>> exec(mycode) Hello world
当你需要expression式的值时,使用eval(string)
:
>>> x = eval("2+2") >>> x 4
但是,第一步应该问自己,如果你真的需要。 执行代码通常应该是最后的手段:如果它包含用户input的代码,它是缓慢,丑陋和危险的。 你应该总是先看看替代scheme,比如更高阶的函数,看看这些能否更好地满足你的需求。
在这个例子中,一个string使用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()
请记住,从版本3 exec
是一个function!
所以总是使用exec(mystring)
而不是exec mystring
。
eval
和exec
是正确的解决scheme,并且可以以更安全的方式使用它们。
正如在Python的参考手册中所讨论的,在本教程中已经清楚地解释过, eval
和exec
函数带有两个额外的参数,允许用户指定可用的全局和本地函数和variables。
例如:
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()
仅用于expression式,而eval('x+1')
起作用, eval('x=1')
不起作用。 在这种情况下,最好使用exec
,甚至更好:尝试find更好的解决scheme:)
使用exec完成执行代码,就像下面的IDLE会话一样:
>>> kw = {} >>> exec( "ret = 4" ) in kw >>> kw['ret'] 4
检查评估 :
x = 1 print eval('x+1') ->2
避免exec
和eval
在Python中使用exec
和eval
是非常令人不悦的。
有更好的select
从最上面的答案(重点是我的):
对于语句,使用
exec
。当你需要expression式的值时,使用
eval
。但是,第一步应该问自己,如果你真的需要。 执行代码通常应该是最后的手段 :如果它包含用户input的代码,它是缓慢,丑陋和危险的。 你应该总是先看看替代scheme,比如更高阶的函数 ,看看这些能否更好地满足你的需求。
从替代到执行/评估?
设置并获取string中名称的variables值
[虽然
eval
]会起作用,但通常不build议使用带有含义的variables名称给程序本身。相反,更好地使用字典。
这不是惯用的
从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是不安全的,即使你删除所有的全局variables和内部variables!
所有这些保护eval()的尝试都是黑名单 。 他们明确地删除可能是危险的东西。 这是一场失败的战斗,因为如果列表中只剩下一个项目,则可以攻击系统 。
那么,可以评估安全吗? 很难说。 在这一点上,我最好的猜测是,如果你不能使用任何双下划线,那么你不能做任何伤害,所以也许如果你排除任何string双下划线,你是安全的。 也许…
这很难阅读和理解
从http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (重点是我的):
首先,
exec
让人们更难阅读你的代码 。 为了弄清楚发生了什么事情,我不仅需要读取代码, 还要读取代码,确定要生成的string,然后读取该虚拟代码。 所以,如果你在一个团队中工作,或者发布开源软件,或者在StackOverflow等地方寻求帮助,那么你就会让其他人更难以帮助你。 如果您有机会在6个月之后debugging或扩展此代码,那么您直接为自己做了更大的努力。
使用eval 。
最合理的解决scheme是使用内置的eval()函数。另一个解决scheme是将该string写入临时的python文件并执行它。
好吧..我知道这不是一个完全的答案,但可能是一个人看我这样的笔记。 我想为不同的用户/客户执行特定的代码,但也想避免exec / eval。 我最初希望将代码存储在每个用户的数据库中,并执行上述操作。
我最终在'customer_filters'文件夹中创build文件系统上的文件,并使用'imp'模块,如果没有filter申请该客户,它只是继续
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