451

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

4

14 回答 14

423

对于语句,请使用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

但是,第一步应该是问问自己是否真的需要。执行代码通常应该是不得已的位置:如果它可以包含用户输入的代码,它会变得缓慢、丑陋和危险。您应该始终首先查看替代方案,例如高阶函数,看看它们是否能更好地满足您的需求。

于 2009-03-31T16:15:24.567 回答
82

在示例中,使用 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()
于 2009-03-31T16:14:38.343 回答
34

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

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

例如:

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

本质上,您正在定义将在其中执行代码的命名空间。

于 2013-02-17T21:44:32.323 回答
22

请记住,从版本 3 开始exec是一个函数!
所以总是使用exec(mystring)而不是exec mystring.

于 2013-06-29T08:49:04.557 回答
15

避免execeval

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

有更好的选择

从最佳答案(强调我的):

对于语句,使用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 个月后调试或扩展此代码,那么您将直接让自己变得更加困难。

于 2016-02-29T19:01:54.950 回答
13

eval()仅用于表达式,例如,虽然eval('x+1')有效,eval('x=1')但不起作用。在这种情况下,最好使用exec,甚至更好:尝试找到更好的解决方案:)

于 2010-11-25T16:03:11.053 回答
9

您可以使用 exec 完成代码的执行,如以下 IDLE 会话:

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

4
于 2012-07-18T22:51:49.133 回答
9

值得一提的是,如果要调用python文件,那exec兄弟也存在。execfile如果您正在使用包含糟糕 IDE 的第三方包并且您想在其包之外进行编码,这有时会很好。

例子:

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

或者:

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

于 2018-01-02T00:42:18.963 回答
8

正如其他人提到的,它是“执行” ..

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

NameError:名称“p_variable”未定义

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
于 2018-11-19T18:29:49.617 回答
5

使用eval

于 2009-03-31T16:13:49.127 回答
5

查看eval

x = 1
print eval('x+1')
->2
于 2009-03-31T16:14:05.770 回答
5

我尝试了很多东西,但唯一有效的是以下内容:

temp_dict = {}
exec("temp_dict['val'] = 10") 
print(temp_dict['val'])

输出:

10

于 2020-05-19T08:36:04.830 回答
1

最合乎逻辑的解决方案是使用内置的eval()函数。另一种解决方案是将该字符串写入临时 python 文件并执行它。

于 2009-03-31T16:15:10.510 回答
1

好的..我知道这不完全是一个答案,但可能是给像我一样看这个的人的注释。我想为不同的用户/客户执行特定的代码,但也想避免 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

于 2017-04-12T13:00:15.600 回答