如何导入外部Python脚本?
我正在用Python写一个游戏引擎,但我不太确定怎么处理外部脚本(比如源引擎的修改,或者LUA脚本)。在游戏中,每个场景和实体都可以有自定义的脚本,但游戏引擎在加载场景之前并不知道这些脚本的存在。举个例子,可能有一个脚本是用来动画游戏中的过场动画的,而这个脚本只会在一个特定的场景中使用。
所以,我想知道处理这些脚本的最佳方法是什么?我知道可以用exec或eval来导入它们,但有人说这样做不安全,为什么呢?我也可以创建一种脚本语言,在运行时解析它,但考虑到Python本身就是一种脚本语言,我觉得这样做没什么意义。任何帮助都会非常感激。
3 个回答
0
你可以通过使用 __import__()
来导入你的外部脚本,或者使用 exec
/ execfile
函数来运行它。了解这些内容是很有帮助的:
- 使用 import 的时候,脚本会被编译成字节码,并在第一次使用时保存一个
.pyc
文件。 - import 会尝试寻找这个 模块,最终会创建一个带有自己命名空间的 模块,而
exec
/execfile
只是简单地执行字符串或文件中的代码。 - 通过在传递全局变量作为参数给
__import__
/execfile
时对内置全局变量进行一些处理,可以稍微限制你的代码运行环境,虽然这种方法并不是特别安全,具体可以参考我对这个问题的 回答。
0
你可以使用 __import__()
这个功能来实现这个目的。假设你的 entity
有一个 script
属性,这个属性可以是 None
(表示没有脚本)或者是一个脚本的名字(这个脚本在一个已知的位置,也就是在 sys.path
中),你可以用下面的代码来运行那个脚本里的 main()
函数:
if entity.script is not None:
custom_script = __import__(entity.script, globals(), locals(), [], -1)
custom_script.main()
0
是的,exec
和 eval
这两个东西在处理用户提供的数据时是不安全的,比如处理表达式或者网页输入。不过,如果你真的想让用户能够使用Python的全部功能,并且你明白这样做的风险(用户可以做任何事情——比如删除或读取电脑上的文件、让Python崩溃、进入无限循环等等),那么使用 exec
是完全可以的。
如果你信任你的游戏脚本设计师,那就可以放心使用 exec
。但如果这些关卡是来自互联网上的随机人,那至少要让你的玩家知道这个风险。