2013-10-17 2 views
2

트위스트 JSON 디코딩 : 내가 사용하는 클라이언트 연결을 실행파이썬 내가 파이썬 트위스트 라이브러리를 사용하여 개발 한 다음 코드를 가지고

class Cache(protocol.Protocol): 
    def __init__(self, factory): 
     self.factory = factory 

    def dataReceived(self, data): 
     request = json.loads(data) 
     self.factory.handle[request['command']](**request) 
     self.transport.write(data) 

class CacheFactory(protocol.Factory): 
    def buildProtocol(self, addr): 
     return Cache(self) 
    def handle_get(self, **kwargs): 
     print 'get\n', kwargs 
    def handle_set(self, **kwargs): 
     print 'set\n', kwargs 
    def handle_delete(self, **kwargs): 
     print 'delete\n', kwargs 
    handle = { 
     'get': handle_get, 
     'set': handle_set, 
     'delete': handle_delete, 
    } 

reactor.listenTCP(int(sys.argv[1]), CacheFactory()) 
reactor.run() 

을 텔넷 :

Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
{"command": "set", "value": 1234567890} 
Connection closed by foreign host. 

이 예외가 발생 :

Traceback (most recent call last): 
    File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 84, in callWithLogger 
    return callWithContext({"system": lp}, func, *args, **kw) 
    File "/usr/lib/python2.7/dist-packages/twisted/python/log.py", line 69, in callWithContext 
    return context.call({ILogContext: newCtx}, func, *args, **kw) 
    File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext 
    return self.currentContext().callWithContext(ctx, func, *args, **kw) 
    File "/usr/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext 
    return func(*args,**kw) 
--- <exception caught here> --- 
    File "/usr/lib/python2.7/dist-packages/twisted/internet/selectreactor.py", line 146, in _doReadOrWrite 
    why = getattr(selectable, method)() 
    File "/usr/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 460, in doRead 
    rval = self.protocol.dataReceived(data) 
    File "./server.py", line 18, in dataReceived 
    self.factory.handle[request['command']](**request) 
exceptions.TypeError: handle_set() takes exactly 1 argument (0 given) 

나는 이해할 수 없다. 라인 self.factory.handle[request['command']](**request)에 문제가있을 수 있지만 제 의견으로는 정확합니다. self 매개 변수를 암시 적으로 전달합니다 (메소드 afterall입니다). 요청 매개 변수를 명시 적으로 압축 해제했습니다. 예외 메시지는 함수가 1 개의 인수를 취하고 거짓말이라고 말합니다. 왜냐하면 2 개의 매개 변수가 필요하기 때문입니다 : self, **kwargs. 그리고 제가 2를 통과 한 이후로 0의 주장을 전달하는 것은 사실이 아닙니다.

누가 문제를 발견하도록 도와 줄 수 있습니까? 그것은 지금으로, handle_* 방법은 인스턴스 메소드입니다

{u'command': u'set', u'value': 1234567890} 

답변

4

, 아직 언 바운드 방법에 handle DICT 포인트 :


이 도움이 경우, JSON 요청으로 디코딩된다. 즉, self은 암시 적으로 전달되지 않습니다. 같은 당신의 handle을 유지할 수, 또는

class CacheFactory(protocol.Factory): 
    def buildProtocol(self, addr): 
     return Cache(self) 
    def handle_get(self, **kwargs): 
     print 'get\n', kwargs 
    def handle_set(self, **kwargs): 
     print 'set\n', kwargs 
    def handle_delete(self, **kwargs): 
     print 'delete\n', kwargs 
    def __init__(self, *args, **kwargs): 
     protocol.Factory.__init__(self, *args, **kwargs) 
     self.handle = { 
      'get': self.handle_get, 
      'set': self.handle_set, 
      'delete': self.handle_delete, 
     } 

이 수행 : 대신이 시도

def dataReceived(self, data): 
     request = json.loads(data) 
     self.factory.handle[request['command']](self.factory, **request) 
     self.transport.write(data) 

을 또는이 방법을 취할 수 다음은 handle 딕셔너리 어느 쪽이든 필요하지 않습니다 :

def dataReceived(self, data): 
     request = json.loads(data) 
     getattr(self.factory, "handle_%s" % (request['command'],))(**request) 
     self.transport.write(data) 

또한 유의하여 dataReceived, 그것은 지금처럼 패킷을 임의로 분할 얻을 수 있기 때문에, 안전하지 않은 - 즉, 한 번에 전체 json 메시지를받지 못할 수도 있습니다.

+0

와우, 독점적 인 설명에 감사드립니다. json 형식의 경우 dataReaded 메소드를 ensafe하려면 어떻게합니까? – ducin

+0

@tkoomzaaskz : [Twisted FAQ] (http://twistedmatrix.com/trac/wiki/ 자주 사용되는 질문 목록을 확인하십시오. 기본적으로받은 모든 데이터의 버퍼를 유지해야하며 프로토콜은 전체 메시지를 받았을 때 알 수 있어야합니다. 귀하의 경우에는 버퍼를 구문 분석하고 실패했는지 확인하여이를 수행 할 수 있습니다.하지만 일종의 길이 정보를 전달하는 것이 좋습니다. 첫 번째 4 바이트는 메시지 크기의 네트워크 바이트 순서로 'uint32'가 될 수 있습니다. – Claudiu

+0

대단히 감사합니다! 추신 : 나는 handler_map-less 솔루션이 가장 좋습니다 – ducin

관련 문제