Ich habe vor, über einen SocketServer Daten zur Verfügung zu stellen, deren Berechnung ziemlich zeitaufwändig ist. Daher habe ich der Klasse (eine Unterklasse von 'dict'), die diese Daten liefert (im Beispiel unten 'MyClass') einen member 'cache' gegeben, der bereits berechnete Daten für zukünftige Anfragen abrufbar halten soll.
Das ganze sieht so aus:
Code: Alles auswählen
import SocketServer
import logging
import time
class MyRequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
return
def handle(self):
self.request.setblocking(0)
total_data = []
data = ''
begin = time.time()
timeout = 2
while True:
if total_data and time.time() - begin > timeout:
break
elif time.time() - begin > timeout * 2:
break
try:
data = self.request.recv(1024)
if data:
total_data.append(data)
begin - time.time()
else:
time.sleep(0.1)
except Exception as e:
pass #logging.exception(e)
complete_request = ''.join(total_data)
result = self.server.handle_request(complete_request)
self.request.send(result)
return
class MyClass(dict):
"""
Autovivifying dictionary with some additional functionality
"""
def __getitem__(self, item):
"""
The autovivification part
"""
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
def __init__(self):
self.logger = logging.getLogger('MyClass')
self.cache = {}
def fill_dict(self):
self['mykey'] = 'myvalue'
def get_result(self, request):
self.logger.info('my keys: %s' % self.keys())
self.logger.info('cache keys: %s' % self.cache.keys())
if request not in self.cache:
self.logger.info('no cached value')
self.cache[request] = 'bar'
self.logger.info('cache keys: %s' % self.cache.keys())
self.logger.info('-' * 80)
return self.cache[request]
class MyServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, handler_class=MyRequestHandler):
self.logger = logging.getLogger('MyServer')
self.myclass_instance = MyClass()
self.myclass_instance.fill_dict()
SocketServer.TCPServer.__init__(self, server_address, handler_class)
return
def handle_request(self, request):
return self.myclass_instance.get_result(request)
def main():
import logging.config
logging.config.fileConfig('/path/to/logconf.ini')
server_address = ('', 8080)
server = MyServer(server_address, MyRequestHandler)
server.serve_forever()
if __name__ == '__main__':
main()
Code: Alles auswählen
import socket
def query(message):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 8080))
len_sent = client.send(message)
complete_response = []
while True:
chunk = client.recv(4096)
if chunk == '':
break
else:
complete_response.append(chunk)
return ''.join(complete_response)
Code: Alles auswählen
2015-09-16 13:06:49,887: [INFO] caching:57 my keys: ['mykey']
2015-09-16 13:06:49,887: [INFO] caching:58 cache keys: []
2015-09-16 13:06:49,887: [INFO] caching:60 no cached value
2015-09-16 13:06:49,887: [INFO] caching:62 cache keys: ['foo']
2015-09-16 13:06:49,887: [INFO] caching:63 --------------------------------------------------------------------------------
2015-09-16 13:06:55,073: [INFO] caching:57 my keys: ['mykey']
2015-09-16 13:06:55,073: [INFO] caching:58 cache keys: []
2015-09-16 13:06:55,073: [INFO] caching:60 no cached value
2015-09-16 13:06:55,074: [INFO] caching:62 cache keys: ['foo']
2015-09-16 13:06:55,074: [INFO] caching:63 --------------------------------------------------------------------------------
Code: Alles auswählen
In [13]: cclient.query('foo')
Out[13]: 'bar'
In [14]: cclient.query('foo')
Out[14]: 'bar'
Wo ist hier mein Denkfehler? Wie kann ich erreichen, dass der Inhalt von self.myclass_instance.cache über mehrere Anfragen hinweg zur Verfügung steht?