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


不要对可能来自程序外部的任何形式的数据使用eval(或exec)。这是一个严重的安全风险。您允许数据的作者在您的计算机上运行任意代码。如果你在这里是因为你想在你的Python程序中按照一个模式创建多个变量,你几乎肯定有一个XY问题。完全不要创建这些变量——相反,适当地使用列表或字典。


当前回答

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

其他回答

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

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

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

输出:

10

查看eval:

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

避免exec和eval

在Python中使用exec和eval是非常不受欢迎的。

有更好的选择

从最上面的答案(重点是我的):

对于语句,使用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(我的重点)

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...

它很难阅读和理解

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

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.