Twisted Python + spawnProcess. Getting output from a command
I'm working to wrap the Minecraft server application with a Twisted Python server that has a RESTful API for getting the list of currently connected players. The Twisted app starts the minecraft server via reactor.spawnProcess(), then communicates via a ProcessTransport, which writes to stdin. Reading stdout and stdin is handled by a separate protocol.ProcessProtocol class.
Given that I want to get the results of a very specific command (the 'list' command, which retu开发者_JS百科rns something like this:
[INFO] Connected players: blah, blah2
If I am able to pick out a player list line in stdout, what is the best way to deliver this to the RESTful API view that is asking for a list of connected players? Keep in mind that my stdout reader can not directly communicate with the function that is trying to get the list of connected players. I can parse stdout and identify the player list for delivery, I'm just not sure how to deliver it to the Web API view that will send the connected player list to a client, since the view and the stdout reader aren't in direct contact.
I've got a few hacky possible ways to handle this, but would much rather do this the "right way" if anyone has ideas.
First, do not call writeSomeData
ever. Call write
. Second, having a global protocol instance is probably a bad idea, for all the usual reasons globals are generally a bad idea.
Third, add a method to the ProcessProtocol
subclass for getting the information you want. The protocol's job is knowing how to turn abstract actions, like "ask for a list of players" into byte sequences to transmit and how to turn received byte sequences back into abstract actions like "the process told me these players are connected".
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)
Now any of your code which has a reference to a connected NotchianProcessProtocol
can call listPlayers
on it and get back a Deferred
which will fire with connected player information shortly afterwards.
精彩评论