运行包含在字符串中的Python代码

Bra*_*eis 8 python pygame eval exec

我正在使用pygame和box2d编写游戏引擎,在角色构建器中,我希望能够编写将在keydown事件上执行的代码.

我的计划是在角色构建器中有一个文本编辑器,让你编写类似于的代码:

if key == K_a:
    ## Move left
    pass
elif key == K_d:
    ## Move right
    pass
Run Code Online (Sandbox Code Playgroud)

我将检索文本编辑器的内容作为字符串,我希望代码在这个Character方法的方法中运行:

def keydown(self, key):
    ## Run code from text editor
Run Code Online (Sandbox Code Playgroud)

最好的方法是什么?

Luc*_*nes 25

您可以使用该eval(string)方法执行此操作.

定义

eval(code, globals=None, locals=None)
代码只是标准的Python代码 - 这意味着它仍然需要正确缩进.

全局变量可以定制自__builtins__定义,这可能对安全性有用.

eval("print('Hello')")
Run Code Online (Sandbox Code Playgroud)

将打印hello到控制台.您还可以为要使用的代码指定本地和全局变量:

eval("print('Hello, %s'%name)", {}, {'name':'person-b'})
Run Code Online (Sandbox Code Playgroud)

安全问题

但要小心.将执行任何用户输入.考虑:

eval("import os;os.system('sudo rm -rf /')")
Run Code Online (Sandbox Code Playgroud)

有很多方法可以解决这个问题.最简单的方法是:

eval("import os;...", {'os':None})
Run Code Online (Sandbox Code Playgroud)

哪个会抛出异常,而不是擦除你的硬盘.虽然你的程序是桌面的,但如果人们重新分发脚本,这可能是一个问题,我想这是有意的.

奇怪的例子

这是一个使用eval相当奇怪的例子:

def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'

eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))
Run Code Online (Sandbox Code Playgroud)

这对eval系列的作用是:

  1. 为当前模块提供另一个名称(它变为contrivedExample脚本).消费者contrivedExample.hello()现在可以打电话.)
  2. 它定义hi为指向hello
  3. 它将该字典与执行模块中的当前全局变量列表相结合.

失败

事实证明(感谢评论者!)您确实需要使用该exec语句.大哎呀.修订后的例子如下:


exec 定义

(这看起来很熟悉!)Exec是一个声明:
exec "code" [in scope] 其中scope是本地变量和全局变量的字典.如果未指定,则在当前范围内执行.

代码只是标准的Python代码 - 这意味着它仍然需要正确缩进.

exec

exec "print('hello')"
Run Code Online (Sandbox Code Playgroud)

将打印hello到控制台.您还可以为要使用的代码指定本地和全局变量:

eval "print('hello, '+name)" in {'name':'person-b'}
Run Code Online (Sandbox Code Playgroud)

exec 安全问题

但要小心.将执行任何用户输入.考虑:

exec "import os;os.system('sudo rm -rf /')"
Run Code Online (Sandbox Code Playgroud)

打印声明

正如评论者所指出的,print是3.0之前的所有Python版本的声明.在2.6中,可以通过键入来更改行为from __future__ import print_statement.否则,使用:

print "hello"
Run Code Online (Sandbox Code Playgroud)

代替 :

print("hello")
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这只适用于python3.在python2.x中,"print"是一个语句,而不是一个函数,所以这给出了语法错误.你需要使用exec代替. (3认同)
  • eval()函数仅支持评估Python表达式,而不支持任意语句.exec语句必须用于语句. (2认同)