当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在Python中执行包含Python代码的字符串?》经验,为你挑选了8个好方法。

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



1> Brian..:

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

2> hekevintran..:

在该示例中,使用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> alan..:

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 "", 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

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


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

4> 小智..:

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



5> 小智..:

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



6> Caridorc..:
避免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个月后调试或扩展这段代码,你就会直接让自己变得更难.



7> 小智..:

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

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

4



8> Pablo Santa ..:

使用eval。


Eval()不执行语句。
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有