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

本文翻译自:How do I execute a string containing Python code in Python?

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


#1楼

参考:https://stackoom.com/question/2wZO/如何在Python中执行包含Python代码的字符串


#2楼

You accomplish executing code using exec, as with the following IDLE session: 您可以使用exec完成执行代码,就像下面的IDLE会话一样:

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

4

#3楼

eval and exec are the correct solution, and they can be used in a safer manner. evalexec是正确的解决方案,可以更安全地使用它们。

As discussed in Python's reference manual and clearly explained in this tutorial, the eval and exec functions take two extra parameters that allow a user to specify what global and local functions and variables are available. 正如Python参考手册中所讨论并在教程中明确说明的那样, evalexec函数带有两个额外的参数,这些参数使用户可以指定可用的全局和局部函数以及变量。

For example: 例如:

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

In essence you are defining the namespace in which the code will be executed. 本质上,您是在定义将在其中执行代码的名称空间。


#4楼

Remember that from version 3 exec is a function! 请记住,从版本3开始, exec是一个函数!
so always use exec(mystring) instead of exec mystring . 因此,请始终使用exec(mystring)而不是exec mystring


#5楼

Avoid exec and eval 避免execeval

Using exec and eval in Python is highly frowned upon. 在Python中使用execeval受到了广泛的反对。

There are better alternatives 有更好的选择

From the top answer (emphasis mine): 从最上面的答案(强调我的):

For statements, use exec . 对于语句,请使用exec

When you need the value of an expression, use eval . 当需要表达式的值时,请使用eval

However, the first step should be to ask yourself if you really need to. 但是,第一步应该是问自己是否真的需要。 Executing code should generally be the position of last resort : It's slow, ugly and dangerous if it can contain user-entered code. 执行代码通常应该是万不得已的方法 :如果它可以包含用户输入的代码,则它很慢,很丑陋而且很危险。 You should always look at alternatives first, such as higher order functions , to see if these can better meet your needs. 您应该始终首先查看替代项,例如高阶函数 ,以查看它们是否可以更好地满足您的需求。

From Alternatives to exec/eval? 替代方案到exec / eval?

set and get values of variables with the names in strings 使用字符串中的名称设置和获取变量的值

[while eval ] would work, it is generally not advised to use variable names bearing a meaning to the program itself. [虽然eval ]有效,但通常不建议使用对程序本身有意义的变量名。

Instead, better use a dict. 相反,最好使用字典。

It is not idiomatic 这不是惯用的

From http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (emphasis mine) 来自http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (重点是我的)

Python is not PHP Python不是PHP

Don't try to circumvent Python idioms because some other language does it differently. 不要试图绕过Python的习惯用法,因为其他一些语言会做不同的事情。 Namespaces are in Python for a reason and just because it gives you the tool exec it does not mean you should use that tool. 在Python中使用命名空间是有原因的, 仅仅是因为它为您提供了工具exec但这并不意味着您应该使用该工具。

It is dangerous 有危险

From http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (emphasis mine) 来自http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (重点是我的)

So eval is not safe, even if you remove all the globals and the builtins! 因此,即使您删除了所有的全局变量和内置函数,eval也不安全!

The problem with all of these attempts to protect eval() is that they are blacklists . 所有这些尝试保护eval()的问题都在于它们是黑名单 They explicitly remove things that could be dangerous. 他们明确删除了可能危险的内容。 That is a losing battle because if there's just one item left off the list, you can attack the system . 那是一场失败的战斗,因为如果只剩下一个项目,那么您可以攻击系统

So, can eval be made safe? 那么,可以使eval安全吗? Hard to say. 很难说。 At this point, my best guess is that you can't do any harm if you can't use any double underscores, so maybe if you exclude any string with double underscores you are safe. 在这一点上,我最好的猜测是,如果您不能使用任何双下划线,那么就不会造成任何伤害,因此,如果您排除任何带有双下划线的字符串,那么您是安全的。 Maybe... 也许...

It is hard to read and understand 很难阅读和理解

From http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (emphasis mine): 来自http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (重点是我):

First, exec makes it harder to human beings to read your code . 首先, exec使人类更难以阅读您的代码 In order to figure out what's happening, I don't just have to read your code, I have to read your code, figure out what string it's going to generate, then read that virtual code. 为了弄清楚发生了什么,我不仅要阅读您的代码, 还必须阅读您的代码,弄清楚它将生成什么字符串,然后阅读该虚拟代码。 So, if you're working on a team, or publishing open source software, or asking for help somewhere like StackOverflow, you're making it harder for other people to help you. 因此,如果您在团队中工作,发布开源软件或在StackOverflow之类的地方寻求帮助,那么其他人将很难为您提供帮助。 And if there's any chance that you're going to be debugging or expanding on this code 6 months from now, you're making it harder for yourself directly. 而且,如果您有机会在6个月后进行该代码的调试或扩展,那么直接给自己增加难度。


#6楼

eval() is just for expressions, while eval('x+1') works, eval('x=1') won't work for example. eval()仅用于表达式,例如eval('x+1')有效,而eval('x=1')无效。 In that case, it's better to use exec , or even better: try to find a better solution :) 在这种情况下,最好使用exec ,甚至更好:尝试找到更好的解决方案:)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值