Twisted Python + spawnProcess. 获取命令输出
我正在尝试把Minecraft服务器应用程序和一个Twisted Python服务器结合起来,这个服务器有一个RESTful API,可以用来获取当前连接的玩家列表。Twisted应用程序通过reactor.spawnProcess()启动Minecraft服务器,然后通过ProcessTransport进行通信,这个过程是写入标准输入(stdin)。读取标准输出(stdout)和标准输入的工作由一个单独的protocol.ProcessProtocol类来处理。
我想获取一个非常特定的命令的结果(就是'list'命令,它返回的内容大概是这样的:
[INFO] Connected players: blah, blah2
如果我能在标准输出中找到玩家列表的那一行,最好的方法是什么来把这个信息传递给请求连接玩家列表的RESTful API视图?请记住,我的标准输出读取器不能直接和试图获取连接玩家列表的函数进行通信。我可以解析标准输出并识别出玩家列表以便传递,但我不太确定如何把它传递给Web API视图,这样才能把连接的玩家列表发送给客户端,因为视图和标准输出读取器并没有直接的联系。
我有一些比较笨的方法可以处理这个问题,但如果有人有更好的想法,我更希望能以“正确的方式”来解决。
1 个回答
首先,别再调用 writeSomeData
了,直接调用 write
。其次,使用全局的协议实例可能不是个好主意,原因和一般情况下全局变量不好的理由是一样的。
第三,给 ProcessProtocol
的子类添加一个方法,用来获取你想要的信息。这个协议的工作就是把一些抽象的操作,比如“请求玩家列表”,转换成可以传输的字节序列,同时也能把接收到的字节序列再转换回抽象的操作,比如“进程告诉我这些玩家已经连接”。
class NotchianProcessProtocol(protocol.ProcessProtocol):
...
def listPlayers(self):
self.transport.write("list")
self._waiting.append(Deferred())
return self._waiting[-1]
def outReceived(self, bytes):
outbuffer = self.outbuffer + bytes
lines, leftover = parseLines(outbuffer)
self.outbuffer = leftover
for line in lines:
if line.startswith('[INFO] Connected players: '):
self._waiting.pop(0).callback(line)
现在,任何有连接的 NotchianProcessProtocol
引用的代码都可以调用 listPlayers
,然后会得到一个 Deferred
,这个 Deferred
会在不久后返回连接的玩家信息。