题
我正在使用pygame和box2d编写游戏引擎,在角色构建器中,我希望能够编写将在keydown事件上执行的代码。
我的计划是在角色构建器中安装一个文本编辑器,让您编写类似于:
的代码if key == K_a:
## Move left
pass
elif key == K_d:
## Move right
pass
我将检索文本编辑器的内容作为字符串,我希望代码在这个Character方法的方法中运行:
def keydown(self, key):
## Run code from text editor
最好的方法是什么?
解决方案
您可以使用 eval(string)
执行此操作的方法。
定义
eval(code,globals = None,locals = None)
代码只是标准的Python代码 - 这意味着它仍然需要正确缩进。
全局变量可以定义自定义 __ builtins __
,这可能对安全性有用。
实施例
eval("print('Hello')")
将 hello
打印到控制台。您还可以为要使用的代码指定本地和全局变量:
eval("print('Hello, %s'%name)", {}, {'name':'person-b'})
安全问题
但是,要小心。将执行任何用户输入。考虑:eval("import os;os.system('sudo rm -rf /')")
有很多方法可以解决这个问题。最简单的方法是做:
eval("import os;...", {'os':None})
这将抛出异常,而不是擦除您的硬盘。虽然你的程序是桌面的,但如果人们重新分发脚本,这可能是一个问题,我想这是有意的。
奇怪的例子
以下是使用 eval
的一个例子:
def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'
eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))
这对评估线的作用是:
- 为当前模块提供另一个名称(它成为脚本的
contrivedExample
)。消费者现在可以调用contrivedExample.hello()
。) - 它将
hi
定义为指向hello
- 它将该字典与执行模块中的当前全局变量列表相结合。 醇>
FAIL
事实证明(感谢评论者!)您确实需要使用 exec
语句。大哎呀。修改后的例子如下:
exec
定义
(看起来很熟悉!)
Exec是一个声明:
exec" code" [范围]
范围是本地和全局变量的字典。如果未指定,则在当前范围内执行。
代码只是标准的Python代码 - 这意味着它仍然需要正确缩进。
exec
示例
exec "print('hello')"
将 hello
打印到控制台。您还可以为要使用的代码指定本地和全局变量:
eval "print('hello, '+name)" in {'name':'person-b'}
exec
安全问题
但是,要小心。将执行任何用户输入。考虑:
exec "import os;os.system('sudo rm -rf /')"
打印声明
正如评论者所指出的, print
是3.0之前的所有Python版本中的语句。在2.6中,可以通过从__future__ import print_statement 键入来更改行为。否则,请使用:
print "hello"
而不是:
print("hello")
其他提示
正如其他人所指出的,您可以将文本加载到字符串中并使用 exec" codestring"
。如果已包含在文件中,则使用 execfile 将避免必须加载它。
一个性能注释:您应该避免多次执行代码,因为解析和编译python源是一个缓慢的过程。即。没有:
def keydown(self, key):
exec user_code
你可以通过将源代码编译成代码对象(使用 compile()
来执行此操作,并通过构建一个可以保留的函数来执行,或者更好地构建一次。要么用户要写“def my_handler(args ...)”,要么自己预先添加,并执行以下操作:
user_source = "def user_func(args):\n" + '\n'.join(" "+line for line in user_source.splitlines())
d={}
exec user_source in d
user_func = d['user_func']
然后:
if key == K_a:
user_func(args)
您可以使用 eval()
eval或exec。在编程之前,你一定要阅读Python库参考。