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

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

How do I execute a string containing Python code in Python?


回答 0

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

但是,第一步应该是问自己是否真的需要。通常,执行代码应该是最后的选择:如果代码中可能包含用户输入的代码,则它很慢,很丑陋而且很危险。您应该始终首先考虑替代项,例如高阶函数,以查看它们是否可以更好地满足您的需求。

For statements, use exec(string) (Python 2/3) or exec string (Python 2):

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

When you need the value of an expression, use eval(string):

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

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.


回答 1

在示例中,使用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()

In the example a string is executed as code using the exec function.

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()

回答 2

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

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

eval and exec are the correct solution, and they can be used in a safer manner.

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.

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.


回答 3

请记住,从版本3开始exec是一个功能!
因此请始终使用exec(mystring)代替exec mystring

Remember that from version 3 exec is a function!
so always use exec(mystring) instead of exec mystring.


回答 4

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

eval() is just for expressions, while eval('x+1') works, eval('x=1') won’t work for example. In that case, it’s better to use exec, or even better: try to find a better solution :)


回答 5

避免execeval

在Python中使用execeval受到了极大的反对。

有更好的选择

从最上面的答案(强调我的):

对于语句,请使用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个月后进行该代码的调试或扩展,那么直接给自己增加难度。

Avoid exec and eval

Using exec and eval in Python is highly frowned upon.

There are better alternatives

From the top answer (emphasis mine):

For statements, use exec.

When you need the value of an expression, use 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?

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.

Instead, better use a dict.

It is not idiomatic

From http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (emphasis mine)

Python is not PHP

Don’t try to circumvent Python idioms because some other language does it differently. 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.

It is dangerous

From http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (emphasis mine)

So eval is not safe, even if you remove all the globals and the builtins!

The problem with all of these attempts to protect eval() is that they are blacklists. 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? 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):

First, exec makes it harder to human beings to read your code. 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. 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

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

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

4

You accomplish executing code using exec, as with the following IDLE session:

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

4

回答 7

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

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

NameError:名称“ p_variable”未定义

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)

As the others mentioned, it’s “exec” ..

but, in case your code contains variables, you can use “global” to access it, also to prevent the compiler to raise the following error:

NameError: name ‘p_variable’ is not defined

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)

回答 8

使用eval


回答 9

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

例:

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

要么:

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

It’s worth mentioning, that’ exec‘s brother exist as well called execfile if you want to call a python file. That is sometimes good if you are working in a third party package which have terrible IDE’s included and you want to code outside of their package.

Example:

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

or:

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


回答 10

查看eval

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

Check out eval:

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

回答 11

我尝试了很多事情,但是唯一可行的事情如下:

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

输出:

10

I tried quite a few things, but the only thing that work was the following:

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

output:

10


回答 12

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

The most logical solution would be to use the built-in eval() function .Another solution is to write that string to a temporary python file and execute it.


回答 13

好吧..我知道这不是一个确切的答案,但可能是对像我一样看这个问题的人的注释。我想为不同的用户/客户执行特定的代码,但也想避免执行/评估。我最初希望将代码存储在每个用户的数据库中,然后执行上述操作。

我最终在“ 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

Ok .. I know this isn’t exactly an answer, but possibly a note for people looking at this as I was. I wanted to execute specific code for different users/customers but also wanted to avoid the exec/eval. I initially looked to storing the code in a database for each user and doing the above.

I ended up creating the files on the file system within a ‘customer_filters’ folder and using the ‘imp’ module, if no filter applied for that customer, it just carried on

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” would execute apply_address_filter from the customer_filters\jj_filter.py file


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。