执行Python代码


Evennia的默认命令集提供的 @py 命令可以让你在游戏中直接执行Python代码。@py 还有个更简单的别名“!”。@py 命令的访问权限应该严格限制。这可不是闹着玩的,在服务器上执行任意Python代码的权限不应交给随便什么人。
@py 1+2
<<< 3


可用的变量

执行 @py 时有一些本地变量可供使用,通过它们可以访问正在运行的系统。
  • self / me —— 调用者(就是你)
  • here —— 调用者的当前位置
  • obj —— 虚拟的物体实例
  • ev —— Evennia的平面API,通过它可以访问Evennia的全部内容。

要访问和你处于同一个房间的其他物体,你可以使用self.search(名称)。要访问其他地点的物体,可以使用的 ev.search_* 方法。请参见后面的内容。


返回输出

在这个例子中,我们会导入并测试 src/utils/utils.py 中的一个工具,也可以通过 ev.utils 访问它:
@py from ev import utils; utils.time_format(33333)
<<< Done.
请注意,我们没有得到任何的返回值,我们只是被告知代码已执行完毕,没有错误发生。这通常发生在较为复杂的无法返回单一值的函数中。为了看到 time_format() 函数的输出,我们需要明确告诉系统用 self.msg() 把结果显示给我们。
@py from ev import utils; self.msg(utils.time_format(33333))
09:15
<<< Done.
如果你在用交互模式运行Evennia(-i 标志),使用 Python 的标准 print 可以在标准输出设备中显示结果(默认是你的终端)。


查找对象

@py 的一个常见用途是在数据库中查找对象,用于调试或执行没有被命令涵盖的特殊操作。

查找对象最好使用 self.search():
@py self.search("red_ball")
<<< Ball

@py self.search("red_ball").db.color = "red"
<<< Done.

@py self.search("red_ball").db.color
<<< red
self.search() 是最常用的方式,但你也可以在数据库的其它表中搜索其它Evennia实体,如脚本或配置。想要这么做,可以使用 ev.search_* 中的通用搜索条目。
@py ev.search_script("sys_game_time")
<<< [<src.utils.gametime.GameTime object at 0x852be2c>]
(请注意,因为这是一条简单的语句,所以我们不需要用 self.msg() 把它包起来以获得输出)。你也可以直接使用数据库模型的管理程序(可通过数据库模型的 objects 属性或 ev.managers.*)。这会更加灵活些,因为它可以让你使用相应管理程序中的所有数据库搜索方法。
@py ev.managers.scripts.script_search("sys_game_time")
<<< [<src.utils.gametime.GameTime object at 0x852be2c>]
管理程序对于数据库的各种查询都很有用。
@py ev.managers.configvalues.all()
<<< [<ConfigValue: default_home]>, <ConfigValue:site_name>, ...]
但在这样做的时候要记住类型类对象和数据库对象之间的区别:使用管理程序的搜索命令会返回类型类,而使用Django默认的搜索方法(get、filter等)会返回数据库对象。这种区别往往会被忽略,但按照惯例,你应该尽量使用管理程序的搜索功能,并在大多数情况下使用类型类。
# 这里使用的是Evennia管理程序的 get_id() 方法
# 它返回角色类型类的实例
@py ev.managers.objects.get_id(1).__class__
<<< Character

# 这里使用的是标准的 Django get() 查询。
# 它返回 Django 数据库模型的实例。
@py ev.managers.objects.get(id=1).__class__
<<< <class 'src.objects.models.ObjectDB'>


游戏外的测试代码

@py 的优势是能在正在运行的服务器中操作(在同一个进程中),这样你可以做实时测试。但大部分这样的工作也可以在游戏之外完成。

进入到 game 目录,并开启一个新的终端。
python manage.py shell
你的默认Python解释器将会启动,配置成能和你的Evennia一同工作,并且导入Evennia安装的所有模块。在这里,可以按你的需要检索数据库并测试运行各个模块。在大多数情况下,你只用 ev 模块就足够了。

建议你使用功能更全的Python解释器,如 iPython。如果你在使用虚拟环境,那你可以通过 pip install ipython 来安装它。iPython可以让你更好地分行工作,还带有很多其他的编辑功能,如tab补全和__doc__字符串读取。
$ python manage.py shell

IPython 0.10 -- An enhanced Interactive Python
...

In [1]: import ev
In [2]: ev.managers.objects.all()
Out[3]: [<ObjectDB: Harry>, <ObjectDB: Limbo>, ...]

在iPython中可以做的事:
  • ev.<tab> —— 这里的<tab>表示在你的键盘上按Tab键。tab补全在iPython的各处都可以工作,既可以将部分输入的文字补全,也可以列出所有可能的结果。本例会列出 ev 中的所有内容。
  • ev.Objects? —— 问号会显示对象的帮助信息(__doc__字符串)。
  • ev.default_cmds.CmdLook?? —— 双问号会显示全部源代码,在本例中是 look 命令的源代码。

更多信息请参阅有关 ev API 的文档。