Python Twisted与Cmd模块集成
我喜欢Python的Twisted和Cmd这两个库。我想把它们结合起来使用。
我已经实现了一些功能,但到目前为止,我还没弄明白怎么让按下Tab键时能自动补全,因为在Twisted的LineReceiver中,我看不到如何立即接收到Tab键的按下事件(而不需要按回车)。
这是我目前的代码:
#!/usr/bin/env python
from cmd import Cmd
from twisted.internet import reactor
from twisted.internet.stdio import StandardIO
from twisted.protocols.basic import LineReceiver
class CommandProcessor(Cmd):
def do_EOF(self, line):
return True
class LineProcessor(LineReceiver):
from os import linesep as delimiter # makes newline work
def __init__(self):
self.processor = CommandProcessor()
self.setRawMode()
def connectionMade(self):
self.transport.write('>>> ')
def rawDataReceived(self, data):
self.processor.onecmd(data)
self.transport.write('>>> ')
StandardIO(LineProcessor())
reactor.run()
除了Tab补全,这个程序基本上是能工作的。我可以输入像“help”这样的命令,Cmd模块会打印出结果。但是我失去了Cmd模块那种很酷的Tab补全功能,因为Twisted是一次只处理一行。我试着把LineProcessor.delimiter
设置为空字符串,但没有效果。也许我需要找Twisted中的其他部分来替代LineReceiver?或者有没有更简单的方法,能让我避免逐个处理每个字符呢?
我不能单独使用Cmd,因为我想把这个做成一个网络应用,其中一些命令会导致发送数据,而从网络接收数据是异步进行的(并且会显示给用户)。
所以无论是从上面的代码开始,还是从其他完全不同的地方开始,我都想在Python中构建一个友好的终端应用,能够响应网络事件和Tab补全。我希望能利用现有的东西,而不需要自己实现太多功能。
1 个回答
9
你在这个方法上遇到了一些困难:
Cmd.onecmd
不会处理按键补全的功能。- 即使它能处理,你的终端也需要处于一种特殊模式,才能让每次按键都能被Python解释器接收到(可以用
tty.setcbreak
来实现这个)。 - 正如你所知道的,
Cmd.cmdloop
不会感知事件,它会一直等待输入。 - 而且,要实现你想要的那些酷炫的行编辑功能,Cmd(实际上是readline)需要直接访问输入和输出。
考虑到这些困难,你可能想让CommandProcessor在自己的线程中运行。比如:
#!/usr/bin/env python
from cmd import Cmd
from twisted.internet import reactor
class CommandProcessor(Cmd):
def do_EOF(self, line):
return True
def do_YEP(self, line):
reactor.callFromThread(on_main_thread, "YEP")
def do_NOPE(self, line):
reactor.callFromThread(on_main_thread, "NOPE")
def on_main_thread(item):
print "doing", item
def heartbeat():
print "heartbeat"
reactor.callLater(1.0, heartbeat)
reactor.callLater(1.0, heartbeat)
reactor.callInThread(CommandProcessor().cmdloop)
reactor.run()