2011-12-19 10 views
6

저는 Python의 TwistedCmd을 좋아합니다. 나는 그들을 함께 사용하고 싶다.Cmd 모듈과의 Python 트위스트 통합

트위스티드의 LineReceiver에서 Tab 키 프레스 이벤트를 (Enter를 누르지 않고)받는 방법을 알지 못하기 때문에 지금까지는 탭 완성 작업을 수행하는 방법을 찾지 못했습니다.

이 외에도 탭 완성에서
#!/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() 

이 다소 작동합니다

여기에 지금까지 내 코드입니다. "help"와 같은 명령을 입력하면 Cmd 모듈이 결과를 인쇄합니다. 그러나 Twisted는 한 번에 한 줄씩 버퍼링하기 때문에 Cmd 모듈의 멋있는 탭 완성 기능을 잃어 버렸습니다. 빈 문자열에 LineProcessor.delimiter을 설정하려고했지만 아무런 소용이 없습니다. 아마도 LineReceiver 대신 Twisted의 다른 조각을 찾아야할까요? 아니면 모든 캐릭터를 하나씩 처리해야하는 것을 피할 수있는 더 간단한 방법이 있을까요?

일부 명령은 데이터를 전송하고 네트워크에서 데이터를받는 것은 비동기식으로 발생하여 사용자에게 표시되는 네트워크 응용 프로그램으로 만들고 싶기 때문에 Cmd 만 사용할 수 없습니다.

우리가 위의 코드에서 시작 했든 완전히 다른 것을 시작하든 관계없이 네트워크 이벤트에 응답하고 탭 완성에 응답하는 멋진 친절한 터미널 응용 프로그램을 Python으로 작성하고 싶습니다. 나는 이미 저 밖에있는 것을 사용할 수 있기를 바래서 너무 많이 구현할 필요가 없기를 바랍니다.

+0

는 [트위스트 맨홀 (http://twistedmatrix.com/trac/wiki/TwistedConch) [실시 예] (http://twistedmatrix.com/documents/current/conch 살펴 /examples/demo_manhole.tac) – jfs

+0

맨홀 (Manhole)과 콘치 (Conch)가 눈치 챘지만, 내가하는 일에 대해서는 나에게별로 의미가 없었습니다. 이 문서에서는 Conch를 SSHv2 구현 (클라이언트와 서버 모두)으로 설명하고 클라이언트에 대한 색상 화를 수행하는 SSH 서버를 만드는 방법을 설명합니다. 내 요구는 비슷하고 다르다. 맨홀을 어떻게 활용할 수 있는지에 대한 구체적인 제안이 있다면, 나는 모든 귀가 있습니다. 문제가되는 것은 문서화가 부족하다는 것입니다. –

답변

9

당신은이 방법으로 문제의 몇 가지있다 :

  • Cmd.onecmd

    어떤 탭 처리를하지 않을 것입니다.
  • 그렇다고하더라도, 개별 키 스트로크가 파이썬 인터프리터로 보내려면 사용자 터미널이 cbreak 모드에 있어야합니다 (tty.setcbreak이 처리 할 수 ​​있습니다).
  • 아시다시피, Cmd.cmdloop은 원자로 인식이 아니므로 입력 대기를 차단합니다.
  • 그러나 멋진 라인 편집을 원한다면 Cmd (실제로는 readline)가 stdin 및 stdout에 직접 액세스 할 수 있어야합니다.

이러한 모든 어려움을 감안할 때 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() 
+0

나는 Tab 키 누르기에서 Cmd 모듈의 완성 방법을 직접 호출 할 생각을하고있었습니다. cbreak를 지적 해 주셔서 감사합니다. 나는 당신의 접근 방식을 시도 할 것이고, 그것을 써 주셔서 감사합니다. –

+0

반갑습니다. 기본적으로 readline은 미니 저주 응용 프로그램입니다. stdin/stdout에 대한 액세스를 조정하려고하면 대부분의 기능을 다시 구현해야 할 필요가 있다고 생각합니다. 이 스레드 접근 방식은 단순하게 유지해야하는 stdin/stdout (cbreak 모드 포함)을 직접 관리합니다. –

+0

twisted.internet.threads.blockingCallFromThread는 CommandProcessor에서 반환 값을 가져올 수있는 매우 유용한 꼬인 함수입니다. –