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

hek*_*ran 315 python string exec

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

Bri*_*ian 296

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

>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world
Run Code Online (Sandbox Code Playgroud)

当您需要表达式的值时,请使用eval(string):

>>> x = eval("2+2")
>>> x
4
Run Code Online (Sandbox Code Playgroud)

但是,第一步应该是问问自己是否真的需要.执行代码通常应该是最后的手段:如果它可以包含用户输入的代码,那么它是缓慢,丑陋和危险的.您应该首先查看备选方案,例如更高阶的功能,看看它们是否能更好地满足您的需求.

  • 有人想要使用'exec'的常见情况类似于`if s =='foo':x.foo = 42 elif s =='bar':x.bar = 42`等,然后他们可以写为`exec("x.%s = 42"%s)`.对于这种常见情况(你只需要访问存储在字符串中的对象的属性),有一个更快,更清洁和更安全的函数`getattr`:只需要写'getattr(x,s)= 42`来表示同一件事情. (20认同)
  • @坦纳:嗯.是的确``setattr(x,s,42)`是正确的语法.感到惊讶的是,这个错误被捕获了很长时间.无论如何,关键是`getattr`和`setattr`是`exec`的替代,当你想要的是获得一个任意成员,用字符串查找. (6认同)
  • exec如何比python解释器慢? (5认同)
  • @ShreevatsaR你的意思是`setattr(x,s,42)`?我试过`getattr(x,2)= 42`它失败了``无法分配给函数调用:<string>,第1行 (4认同)

hek*_*ran 63

在该示例中,使用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()
Run Code Online (Sandbox Code Playgroud)

  • @Narcolapser,你应该更关心使用“exec”(除非你_知道_代码字符串来自可信来源)。 (3认同)
  • 像这样交换 stdout 和 stderr 让我非常紧张。这看起来可能会导致巨大的安全问题。有没有办法解决这个问题? (2认同)

ala*_*lan 24

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

正如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
Run Code Online (Sandbox Code Playgroud)

实际上,您正在定义将在其中执行代码的命名空间.

  • 不可能使eval安全:[Eval真的很危险](http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html).如果您从我那里获取代码并对其进行评估,我可以对您的Python程序进行分段.游戏结束. (8认同)
  • @ v.oddou我回应了阿兰的声明,"eval和exec ..可以安全地使用." 这是错误的.如果有人说"bash可以安全使用",那也是错误的.Bash很危险.这是一种必要的危险,但仍然是危险的.声称eval可以安全是完全错误的. (2认同)
  • @NedBatchelder用Python编写的许多代码也可能很危险,但是为什么要假设将`eval`或`exec`用作`exec(input(“输入所需内容”)))?在许多情况下,程序可能会根据计算结果编写过程或函数;产生的功能将与良好且编写良好的程序的任何其他部分一样安全,快捷(一旦评估)。_包含exec的不安全程序不会比不安全的程序本身造成损害,因为exec不会给程序带来任何新的特权。 (2认同)

小智 21

请记住,版本3 exec是一个功能!
所以总是用exec(mystring)而不是exec mystring.


小智 11

eval()仅仅是表达式,而eval('x+1')作品,eval('x=1')不会起作用.在这种情况下,最好使用exec,甚至更好:尝试找到更好的解决方案:)


Car*_*orc 11

避免execeval

在Python中使用execeval非常不受欢迎.

有更好的选择

从最顶层的答案(强调我的):

对于陈述,请使用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个月后调试或扩展这段代码,你就会直接让自己变得更难.


小智 9

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

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

4
Run Code Online (Sandbox Code Playgroud)

  • 这在普通 python 中不起作用。至少不是在python 3中。 (3认同)

use*_*754 9

值得一提的是,如果你想调用一个python文件,那'exec的兄弟也存在execfile。如果您在包含糟糕的 IDE 的第三方软件包中工作并且您想在它们的软件包之外编码,这有时会很好。

例子:

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

或者:

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


Gha*_*nem 8

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

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

NameError: name 'p_variable' 未定义

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
Run Code Online (Sandbox Code Playgroud)


pau*_*uvo 6

我尝试了很多方法,但唯一有效的方法如下:

temp_dict = {}
exec("temp_dict['val'] = 10") 
print(temp_dict['val'])
Run Code Online (Sandbox Code Playgroud)

输出:

10

  • 尝试了上述大部分方法后,这是唯一有效的方法。格拉西亚斯 (2认同)

Pab*_*ruz 5

使用eval

  • Eval()不执行语句。 (6认同)