Python Twisted与Cmd模块的集成



我喜欢Python的Twisted和Cmd。我想把它们一起使用。

我得到了一些工作,但到目前为止,我还没有弄清楚如何使制表符完成工作,因为我没有看到如何接收制表符按键事件立即(不按Enter)在Twisted的linerreceiver。

下面是目前为止的代码:
#!/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()

除了制表符补全之外,这在一定程度上是有效的。我可以输入像"帮助"这样的命令,Cmd模块将打印结果。但是我失去了Cmd模块的漂亮的选项卡完成功能,因为Twisted每次缓冲一行。我尝试将LineProcessor.delimiter设置为空字符串,但无济于事。也许我需要找一些其他的Twisted来代替LineReceiver?或者是否存在一种更简单的方法,可以避免我逐个处理每个字符?

我不能单独使用Cmd,因为我想使其成为一个网络应用程序,其中一些命令将导致发送数据,并且从网络接收数据将异步发生(并显示给用户)。

因此,无论我们是从上面的代码开始还是从完全不同的代码开始,我都想用Python构建一个漂亮、友好的终端应用程序,它可以响应网络事件和选项卡补全。我希望我可以使用已经存在的东西,而不必自己实现太多。

使用这种方法有几个困难:

  • Cmd.onecmd不做任何标签处理。
  • 即使是这样,你的终端也需要处于cbreak模式,以便每个按键都能进入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()

最新更新