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

发布于 2024-07-24 13:15:48 字数 381 浏览 5 评论 0原文

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

我的计划是在字符生成器中拥有一个文本编辑器,让您编写类似于以下内容的代码:

if key == K_a:
    ## Move left
    pass
elif key == K_d:
    ## Move right
    pass

我将以字符串形式检索文本编辑器的内容,并且我希望代码在该字符方法中的方法中运行:

def keydown(self, key):
    ## Run code from text editor

最好的方法是什么?

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

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

What's the best way to do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧伤慢歌 2024-07-31 13:15:48

您可以使用 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()))

它在 eval 行上的作用是:

  1. 给当前模块另一个名称(对于脚本来说它变成了 contrivedExample)。 消费者现在可以调用 contrivedExample.hello()。)
  2. 它将 hi 定义为指向 hello
  3. 它将该字典与当前全局变量列表结合起来在执行模块中。

失败 事实

证明(感谢评论者!)您实际上需要使用 exec 语句。 大哎呀。 修改后的示例如下:


exec 定义

(这看起来很熟悉!)
Exec 是一条语句:
exec“code”[在范围内]
其中,scope 是局部变量和全局变量的字典。 如果未指定,它将在当前范围内执行。

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

exec 示例

exec "print('hello')"

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

eval "print('hello, '+name)" in {'name':'person-b'}

exec 安全问题

不过要小心。 任何用户输入都会被执行。 考虑:

exec "import os;os.system('sudo rm -rf /')"

Print 语句

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

print "hello"

而不是:

print("hello")

You can use the eval(string) method to do this.

Definition

eval(code, globals=None, locals=None)
The code is just standard Python code - this means that it still needs to be properly indented.

The globals can have a custom __builtins__ defined, which could be useful for security purposes.

Example

eval("print('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.

Strange Example

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

What this does on the eval line is:

  1. Gives the current module another name (it becomes contrivedExample to the script). The consumer can call contrivedExample.hello() now.)
  2. It defines hi as pointing to hello
  3. It combined that dictionary with the list of current globals in the executing module.

FAIL

It turns out (thanks commenters!) that you actually need to use the exec statement. Big oops. The revised examples are as follows:


exec Definition

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

The code is just standard Python code - this means that it still needs to be properly indented.

exec Example

exec "print('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 Security Concerns

Be careful, though. Any user input will be executed. Consider:

exec "import os;os.system('sudo rm -rf /')"

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"

Instead of :

print("hello")
韬韬不绝 2024-07-31 13:15:48

正如其他人所指出的,您可以将文本加载到字符串中并使用 exec "codestring"。 如果已包含在文件中,则使用 execfile 将避免加载它。

一个性能说明:您应该避免多次执行代码,因为解析和编译 python 源代码是一个缓慢的过程。 IE。 没有:

def keydown(self, key):
    exec user_code

您可以通过将源代码编译为代码对象(使用 compile() 和 exec 来改进这一点,或者更好的是,通过构造一个您保留的函数,并且只构建要么要求用户编写“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)

As others have pointed out, you can load the text into a string and use exec "codestring". If contained in a file already, using execfile will avoid having to load it.

One performance note: You should avoid execing the code multiple times, as parsing and compiling the python source is a slow process. ie. don't have:

def keydown(self, key):
    exec user_code

You can improve this a little by compiling the source into a code object (with compile() and exec that, or better, by constructing a function that you keep around, and only build once. Either require the user to write "def my_handler(args...)", or prepend it yourself, and do something like:

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']

Then later:

if key == K_a:
   user_func(args)
素衣风尘叹 2024-07-31 13:15:48

您可以使用 eval()

You can use eval()

乖乖哒 2024-07-31 13:15:48

评估或执行。 在编程之前你一定应该阅读Python库参考。

eval or exec. You should definitely read Python library reference before programming.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文