简体   繁体   English

Python Twisted与Cmd模块的集成

[英]Python Twisted integration with Cmd module

I like Python's Twisted and Cmd . 我喜欢Python的TwistedCmd I want to use them together. 我想一起使用它们。

I got some things working, but so far I haven't figured out how to make tab-completion work, because I don't see how to receive tab keypres events right away (without pressing Enter) in Twisted's LineReceiver. 我有一些工作,但到目前为止,我还没有想出如何使标签完成工作,因为我没有看到如何在Twisted的LineReceiver中立即接收Tab键盘事件(不按Enter键)。

Here's my code so far: 到目前为止,这是我的代码:

#!/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()

Apart from tab completion, this somewhat works. 除了标签完成,这有点起作用。 I can enter a command like "help" and the Cmd module will print the results. 我可以输入“help”之类的命令,Cmd模块将打印结果。 But I've lost the nifty tab-complete functionality of the Cmd module, because Twisted is buffering one line at a time. 但是我已经失去了Cmd模块的漂亮的tab-complete功能,因为Twisted一次缓冲一行。 I tried setting LineProcessor.delimiter to the empty string, to no avail. 我尝试将LineProcessor.delimiter设置为空字符串,但无济于事。 Maybe I need to find some other piece of Twisted to use instead of LineReceiver? 也许我需要找一些其他的Twisted而不是LineReceiver? Or maybe there's a simpler approach that will avoid my having to process every character one-by-one? 或者也许有一种更简单的方法可以避免我必须逐个处理每个字符?

I can't use Cmd alone, because I want to make this a network application, where some commands will result in sending data, and receiving data from the network will happen asynchronously (and be displayed to the user). 我不能单独使用Cmd,因为我想把它变成一个网络应用程序,其中一些命令将导致发送数据,并且从网络接收数据将异步发生(并显示给用户)。

So whether we start from the above code or something completely different, I'd like to build a nice, friendly terminal application in Python that responds to network events and also to tab completion. 因此,无论我们从上面的代码还是完全不同的东西开始,我都想在Python中构建一个友好的,友好的终端应用程序,它响应网络事件和标签完成。 I hope I can use what's already out there and not have to implement too much myself. 我希望我可以使用已经存在的东西而不必自己实施太多。

You have a couple of difficulties with this approach: 这种方法有两个困难:

  • Cmd.onecmd is not going to do any tab processing. Cmd.onecmd不会进行任何制表处理。
  • Even if it did, your terminal needs to be in cbreak mode in order for individual keystrokes to make it to the Python interpreter ( tty.setcbreak can take care of that). 即使它确实如此,您的终端也需要处于cbreak模式,以便单独按键才能将其转换为Python解释器( tty.setcbreak可以解决这个问题)。
  • As you know, Cmd.cmdloop is not reactor aware and will block waiting for input. 如您所知, Cmd.cmdloop不支持reactor,并将阻止等待输入。
  • Yet, to get all of the cool line-editing you want, Cmd (actually readline) needs to have direct access to stdin and stdout. 然而,为了获得你想要的所有酷线编辑,Cmd(实际上是readline)需要直接访问stdin和stdout。

Given all of these difficulties, you might want to look at letting the CommandProcessor run in its own thread. 鉴于所有这些困难,您可能希望看看让CommandProcessor在其自己的线程中运行。 For example: 例如:

#!/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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM