gpt4 book ai didi

python - 在 Python 中创建简单的脚本语言

转载 作者:太空狗 更新时间:2023-10-29 18:17:00 25 4
gpt4 key购买 nike

我正在创建一个可以监视和操作消息流的 GUI 应用程序。我正在尝试创建一种简单的方法来让用户编写其中一些功能的脚本,并且我正在寻找可能的候选者。最初我想使用 XML,因为它可以自然地处理嵌入式代码:

<if>
<condition>
<recv>
<MesgTypeA/>
</recv>
</condition>
<loop count=10>
<send>
<MesgTypeB>
<param1>12</param1>
<param2>52</param2>
</MesgTypeB>
</send>
</loop>
</if>

对于解析,我计划使用 ElementTree 并从代码中构建状态。编写和读取 XML 并不是一件容易的事情,尤其是因为我不能假设脚本的编写者会有任何经验。我想知道是否有人有任何更容易在 Python 中读/写和处理的替代方案。我查看了 JSON,但因为它是一个脚本,所以顺序很重要。

谁能提出任何可能的替代方案?

谢谢。

最佳答案

Python 怎么样 itself

例如:

>>> import code
>>> def host_func():
... print("Hello old chap!")
...
>>> c = code.compile_command("print(\"Script says hello!\"); host_func()")
>>> exec(c)
Script says hello!
Hello old chap!

exec让我们通过两个可选参数 localsglobals 明确说明您希望从主机环境公开什么。

在这个例子中,我明确说明脚本可以访问哪些全局变量。请注意,我可以在此处“创建”变量,或为现有函数指定另一个名称。它是指向函数和数据的字典。

>>> import code
>>> def secret():
... print("What?! I don't even... get out of here.")
...
>>> def public():
... print("Hello stranger.")
...
>>> c = code.compile_command("secret(); public()")

用包含两个函数的全局变量调用它,指向已经存在的函数给出:

>>> exec(c, {"secret": secret, "public": public})
What?! I don't even... get out of here.
Hello stranger.

现在,当我省略 secret 时,脚本将无法再找到它。

>>> exec(c, {"public": public})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<input>", line 1, in <module>
NameError: name 'secret' is not defined

这里我重新定义了secret:

>>> exec(c, {"public": public, "secret":lambda: print("Haha! Doppelganger.")})
Haha! Doppelganger.
Hello stranger.

作为lazyr评论中提到存在安全问题。上面的例子让脚本几乎可以做它想做的事。在某些情况下,这是 Not Acceptable 。

有一些方法可以阻止它:

  • 中性__builtins__,只允许“白名单”内置函数。
  • 使导入模块变得困难。

例如,下面是您如何使用 import 语句(在 Py2.* builtins 中是 __builtins__):

>>> import builtins
>>> def no_import(*args, **kwargs):
... raise ImportError("I cannot let you do that, Dave.")
...
>>> builtins.__import__ = no_import
>>> import os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in no_import
ImportError: I cannot let you do that, Dave.

由此可见,我们可以在全局参数中传递我们自己的 builtins:

>>> import code
>>> evil_code = "import os; import stat; os.chmod(\"passwords.txt\", stat.S_IROT
H);"
>>> compiled = code.compile_command(evil_code)
>>> def no_import(*args, **kwargs):
... raise ImportError("I cannot let you do that, Dave.")
...
>>> exec(compiled, {"__builtins__": {"__import__": no_import}})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<input>", line 1, in <module>
File "<stdin>", line 2, in no_import
ImportError: I cannot let you do that, Dave.

不过,需要注意的是,这会阻碍所有在它之后发生的导入。最好将其替换为允许您导入列入白名单的模块的版本。

最后,我不确定这是否能完全保护您。一些狡猾的人可能会规避它。但至少应该劝阻最公然的违规行为。

关于python - 在 Python 中创建简单的脚本语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6535748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com