如何在Python中执行包含Python代码的字符串?

如何在Python中执行包含Python代码的字符串?

457655 次浏览

使用eval

查看eval:

x = 1
print eval('x+1')
->2

在本例中,使用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 ()函数。另一种解决方案是将该字符串写入临时python文件并执行它。

对于语句,使用exec(string) (Python 2/3)或exec string (Python 2):

>>> my_code = 'print("hello world")'
>>> exec(my_code)
Hello world

当你需要一个表达式的值时,使用eval(string):

>>> x = eval("2+2")
>>> x
4

然而,第一步应该是问自己是否真的需要这样做。执行代码通常应该是最后的手段:如果它包含用户输入的代码,那么它就会变得缓慢、丑陋和危险。你应该总是先看看替代方案,比如高阶函数,看看它们是否能更好地满足你的需求。

eval()只是用于表达式,而eval('x+1')可以工作,例如eval('x=1')就不能工作。在这种情况下,最好使用exec,或者更好:尝试找到一个更好的解决方案:)

你可以使用exec完成代码的执行,就像下面的IDLE会话一样:

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']


4

evalexec是正确的解决方案,它们可以以更安全的的方式使用。

正如Python参考手册中所讨论的,并在教程中明确解释的那样,evalexec函数有两个额外的参数,允许用户指定可用的全局和局部函数和变量。

例如:

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

实际上,您是在定义代码将在其中执行的名称空间。

记住,从版本3 exec是一个函数!< br > 所以总是使用exec(mystring)而不是exec mystring

避免execeval

在Python中使用execeval是非常不受欢迎的。

有更好的选择

从最上面的答案(重点是我的):

对于语句,使用exec

当你需要表达式的值时,使用eval

然而,第一步应该是问自己是否真的需要这样做。执行代码通常应该是最后的选择:如果它包含用户输入的代码,它是缓慢的,丑陋的和危险的。你应该经常查看首先是备选方案,比如高阶函数,看看这些是否能更好地满足你的需求。

exec/eval的替代方案?

设置并获取字符串形式的变量的值

[虽然eval]可以工作,但通常不建议使用对程序本身有意义的变量名。

相反,最好使用字典。

它不是惯用的

来自http://lucumr.pocoo.org/2011/2/1/exec-in-python/(强调我的)

Python不是PHP

不要试图规避Python习惯用语,因为其他语言的做法不同。命名空间在Python中是有原因的,并且仅仅因为它给了你工具exec,这并不意味着你应该使用这个工具。 . c

这很危险

来自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/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)

so customerName = "jj" 将执行apply_address_filter从customer_filters\jj_filter.py文件

值得一提的是,如果你想调用一个Python文件,exec的兄弟也存在,称为execfile。如果你在第三方包中工作,其中包含了糟糕的IDE,而你想在他们的包外编码,这有时是件好事。

例子:

execfile('/path/to/source.py')

或者:

exec(open("/path/to/source.py").read())

就像其他人提到的,是“exec”。

但是,如果你的代码包含变量,你可以使用"global"来访问它,也可以防止编译器引发以下错误:

NameError: name '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