2
我有下面的代碼使用Python扭圖書館編制:蟒蛇絞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
參數(它是一種方法後繼)和解壓縮的請求參數。異常消息說該函數需要1個參數,並且它是一個謊言:),因爲它需要2個參數:self, **kwargs
。而且,由於我通過了2,所以我傳遞了0個參數並不是真的。
有人能幫我發現問題嗎?
的情況下,它可以幫助,json的請求被解碼爲:
{u'command': u'set', u'value': 1234567890}
哇,謝謝你的獨家解釋。如果使用json格式,你會怎樣保護dataReceived方法? – ducin
@tkoomzaaskz:查看[Twisted FAQ](http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#Whyisprotocol.dataReceivedcalledwithonlypartofthedataataIdledTransport.writewith)。基本上,您必須保留所收到的所有數據的緩衝區,並且您的協議必須能夠知道您何時收到完整的消息。在你的情況下,你可以通過嘗試解析緩衝區並查看是否失敗來做到這一點,我猜,但最好傳遞一些長度信息,例如前4個字節可以是消息大小的網絡字節順序的「uint32」。 – Claudiu
非常感謝! PS我喜歡handler_map-less解決方案最好的 – ducin