运行包含在字符串中的 Python 代码 [英] Running Python code contained in a string
问题描述
我正在使用 pygame 和 box2d 编写游戏引擎,并且在角色构建器中,我希望能够编写将在 keydown 事件上执行的代码.
I'm writing a game engine using pygame and box2d, and in the character builder, I want to be able to write the code that will be executed on keydown events.
我的计划是在字符生成器中有一个文本编辑器,让您可以编写类似于以下内容的代码:
My plan was to have a text editor in the character builder that let you write code similar to:
if key == K_a:
## Move left
pass
elif key == K_d:
## Move right
pass
我将文本编辑器的内容检索为字符串,并且我希望代码在Character的这个方法中的一个方法中运行:
I will retrieve the contents of the text editor as a string, and I want the code to be run in a method in this method of Character:
def keydown(self, key):
## Run code from text editor
最好的方法是什么?
推荐答案
您可以使用 eval(string)
方法来做到这一点.
You can use the eval(string)
method to do this.
eval(code, globals=None, locals=None)
代码只是标准的 Python 代码——这意味着它仍然需要正确缩进.
eval(code, globals=None, locals=None)
The code is just standard Python code - this means that it still needs to be properly indented.
全局变量可以定义一个自定义的 __builtins__
,这对于安全目的可能很有用.
The globals can have a custom __builtins__
defined, which could be useful for security purposes.
eval("print('Hello')")
会将 hello
打印到控制台.您还可以为要使用的代码指定局部和全局变量:
Would print hello
to the console. You can also specify local and global variables for the code to use:
eval("print('Hello, %s'%name)", {}, {'name':'person-b'})
安全问题
不过要小心.将执行任何用户输入.考虑:
Security Concerns
Be careful, though. Any user input will be executed. Consider:
eval("import os;os.system('sudo rm -rf /')")
有很多方法可以解决这个问题.最简单的方法是执行以下操作:
There are a number of ways around that. The easiest is to do something like:
eval("import os;...", {'os':None})
这将引发异常,而不是擦除您的硬盘驱动器.虽然您的程序是桌面程序,但如果人们重新分发脚本,这可能是一个问题,我想这是有意的.
Which will throw an exception, rather than erasing your hard drive. While your program is desktop, this could be a problem if people redistributed scripts, which I imagine is intended.
这是一个使用 eval
的例子,相当奇怪:
Here's an example of using eval
rather strangely:
def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'
eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))
这在 eval 行的作用是:
What this does on the eval line is:
- 为当前模块赋予另一个名称(它成为脚本的
contrivedExample
).消费者现在可以调用contrivedExample.hello()
.) - 它将
hi
定义为指向hello
- 它将字典与执行模块中的当前全局变量列表结合起来.
- Gives the current module another name (it becomes
contrivedExample
to the script). The consumer can callcontrivedExample.hello()
now.) - It defines
hi
as pointing tohello
- It combined that dictionary with the list of current globals in the executing module.
失败
事实证明(感谢评论者!)您实际上需要使用 exec
语句.大哎哟.修改后的例子如下:
FAIL
It turns out (thanks commenters!) that you actually need to use the exec
statement. Big oops. The revised examples are as follows:
(这看起来很熟悉!)Exec 是一个语句:exec "code" [in scope]
其中范围是局部和全局变量的字典.如果未指定,则在当前范围内执行.
(This looks familiar!)
Exec is a statement:
exec "code" [in scope]
Where scope is a dictionary of both local and global variables. If this is not specified, it executes in the current scope.
代码只是标准的 Python 代码 - 这意味着它仍然需要正确缩进.
The code is just standard Python code - this means that it still needs to be properly indented.
exec "print('hello')"
会将 hello
打印到控制台.您还可以为要使用的代码指定局部和全局变量:
Would print hello
to the console. You can also specify local and global variables for the code to use:
eval "print('hello, '+name)" in {'name':'person-b'}
exec
安全问题
不过要小心.将执行任何用户输入.考虑:
exec
Security Concerns
Be careful, though. Any user input will be executed. Consider:
exec "import os;os.system('sudo rm -rf /')"
<小时>
打印声明
正如评论者所指出的,print
是 Python 3.0 之前的所有版本中的声明.在 2.6 中,可以通过键入 from __future__ import print_statement
来更改行为.否则,使用:
Print Statement
As also noted by commenters, print
is a statement in all versions of Python prior to 3.0. In 2.6, the behaviour can be changed by typing from __future__ import print_statement
. Otherwise, use:
print "hello"
代替:
print("hello")
这篇关于运行包含在字符串中的 Python 代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!