Seite 1 von 1
multiprocessing & HTTPConnection
Verfasst: Freitag 29. August 2014, 10:14
von Boa
Hi,
Ich versuche eine Funktion zu schreiben, die einen HTTP Download mit einem Timeout kombiniert. Dabei sollen außerdem die Verbindungen gecached werden. Die Lösung mit eventlet habe ich fürs erste aufgegeben, weil ich die Fehlermeldungen nicht deuten konnte, die ich in meinem Programm bekam. Nun versuche ich es erst Mal mit multiprocessing, auch wenn es nicht so schön ist.
Beim Zuweisen einer HTTPConnection an mein multiprocessing dict bekomme ich bei mir einen Fehler:
PicklingError: Can't pickle httplib.HTTPConnection: it's not the same object as httplib.HTTPConnection
Ich habe versucht das Problem nachzustellen, bekomme dabei aber noch einen anderen Fehler mit dem ich nichts anfangen kann:
Code: Alles auswählen
import httplib
from multiprocessing import Manager
from multiprocessing import Process
manager = Manager()
conn_pool = manager.dict()
def f():
conn_pool[1]=httplib.HTTPConnection("www.google.de")
p = Process(target=f, args=())
p.start()
Code: Alles auswählen
Process Process-2:
Traceback (most recent call last):
File "/usr/lib/python2.6/multiprocessing/process.py", line 232, in _bootstrap
self.run()
File "/usr/lib/python2.6/multiprocessing/process.py", line 88, in run
self._target(*self._args, **self._kwargs)
File "test.py", line 10, in f
conn_pool[1]=httplib.HTTPConnection("www.google.de")
File "<string>", line 2, in __setitem__
File "/usr/lib/python2.6/multiprocessing/managers.py", line 722, in _callmethod
self._connect()
File "/usr/lib/python2.6/multiprocessing/managers.py", line 709, in _connect
conn = self._Client(self._token.address, authkey=self._authkey)
File "/usr/lib/python2.6/multiprocessing/connection.py", line 149, in Client
answer_challenge(c, authkey)
File "/usr/lib/python2.6/multiprocessing/connection.py", line 383, in answer_challenge
message = connection.recv_bytes(256) # reject large message
EOFError
Vielleicht kennt ihr eine Lösung oder könnt mir einen Tipp geben.
Thx,
Boa
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 09:47
von Boa
Hmm, ich denke ich werde die Verbindungen einfach in ein shelve o.ä. packen um sie zwischen den Prozessen auszutauschen. Mit httplib2 hat es übrigens auch nicht geklappt.
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 13:41
von BlackJack
@Boa: Du kannst so etwas wie eine Netzwerkverbindung nicht serialisieren. Da hängen Zustandsinformationen mit zusammen die Du vom Betriebssystem gar nicht in die Finger bekommst und die man deshalb auch gar nicht wieder herstellen könnte wenn man die Verbindung deserialisiert.
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 14:23
von Boa
BlackJack hat geschrieben:@Boa: Du kannst so etwas wie eine Netzwerkverbindung nicht serialisieren. Da hängen Zustandsinformationen mit zusammen die Du vom Betriebssystem gar nicht in die Finger bekommst und die man deshalb auch gar nicht wieder herstellen könnte wenn man die Verbindung deserialisiert.
Was genau lässt sich bei dem Socket nicht serialisieren? Unter Linux sind Sockets soweit ich weiß doch nur spezielle Dateien. Mit pickle habe ich bisher auch keine Probleme festgestellt.
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 14:46
von BlackJack
@Boa: Tja und Dateiobjekte kann man auch nicht serialisieren.
Code: Alles auswählen
In [1]: import pickle
In [2]: f = open('test.py')
In [3]: pickle.dumps(f)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-03b30dfeb586> in <module>()
----> 1 pickle.dumps(f)
/usr/lib/python2.7/pickle.pyc in dumps(obj, protocol)
1372 def dumps(obj, protocol=None):
1373 file = StringIO()
-> 1374 Pickler(file, protocol).dump(obj)
1375 return file.getvalue()
1376
/usr/lib/python2.7/pickle.pyc in dump(self, obj)
222 if self.proto >= 2:
223 self.write(PROTO + chr(self.proto))
--> 224 self.save(obj)
225 self.write(STOP)
226
/usr/lib/python2.7/pickle.pyc in save(self, obj)
304 reduce = getattr(obj, "__reduce_ex__", None)
305 if reduce:
--> 306 rv = reduce(self.proto)
307 else:
308 reduce = getattr(obj, "__reduce__", None)
/usr/lib/python2.7/copy_reg.pyc in _reduce_ex(self, proto)
68 else:
69 if base is self.__class__:
---> 70 raise TypeError, "can't pickle %s objects" % base.__name__
71 state = base(self)
72 args = (self.__class__, base, state)
TypeError: can't pickle file objects
Du bekommst von Dateien als Programmierer letztendlich immer nur eine Zahl oder einen opaken Zeiger in die Hand. Alle anderen Informationen die zu einer offenen Datei gehören, kennt nur das Betriebsystem. Dazu kommt noch das diese Zahl nur innerhalb eines Prozesses gültig ist. Zwei verschiedene Prozesse können die gleiche Zahl vom Betriebssystem bekommen, die steht aber jeweils für eine andere Datei. Deshalb kann man diese Zahl auch nicht einfach an einen anderen Prozess weitergeben.
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 15:44
von snafu
Boa hat geschrieben:Dabei sollen außerdem die Verbindungen gecached werden
Was erhoffst du dir von diesem Vorgehen?
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 16:33
von Boa
Also mit Pickle ließ sich httplib.HTTPConnection serialisieren. Bleibt noch die Frage ob das tatsächlich die Verbindung aufrecht erhält.
@snafu: Geschwindigkeit bei vielen Anfragen - dazu gibt es ja den Connection: keep-alive header
ot:
@BlackJack: Im Prinzip funktioniert das: stackoverflow.com/questions/1075443/share-objects-with-file-handle-attribute-between-processes
Sockets kann man auch weitergeben:
http://www.normalesup.org/~george/comp/libancillary/
Re: multiprocessing & HTTPConnection
Verfasst: Sonntag 31. August 2014, 16:47
von BlackJack
@Boa: Also ich kann keine *bestehende* Verbindung serialisieren, nur unverbundene `HTTPConnection`\s:
Code: Alles auswählen
In [12]: c = httplib.HTTPConnection('www.python-forum.de')
In [13]: x = pickle.dumps(c) # Geht.
In [14]: c.connect()
In [15]: pickle.dumps(c) # Geht nicht mehr.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-49ce1ecf77bc> in <module>()
----> 1 pickle.dumps(c)
/usr/lib/python2.7/pickle.pyc in dumps(obj, protocol)
1372 def dumps(obj, protocol=None):
1373 file = StringIO()
-> 1374 Pickler(file, protocol).dump(obj)
1375 return file.getvalue()
1376
/usr/lib/python2.7/pickle.pyc in dump(self, obj)
222 if self.proto >= 2:
223 self.write(PROTO + chr(self.proto))
--> 224 self.save(obj)
225 self.write(STOP)
226
/usr/lib/python2.7/pickle.pyc in save(self, obj)
284 f = self.dispatch.get(t)
285 if f:
--> 286 f(self, obj) # Call unbound method with explicit self
287 return
288
/usr/lib/python2.7/pickle.pyc in save_inst(self, obj)
723 stuff = getstate()
724 _keep_alive(stuff, memo)
--> 725 save(stuff)
726 write(BUILD)
727
/usr/lib/python2.7/pickle.pyc in save(self, obj)
284 f = self.dispatch.get(t)
285 if f:
--> 286 f(self, obj) # Call unbound method with explicit self
287 return
288
/usr/lib/python2.7/pickle.pyc in save_dict(self, obj)
647
648 self.memoize(obj)
--> 649 self._batch_setitems(obj.iteritems())
650
651 dispatch[DictionaryType] = save_dict
/usr/lib/python2.7/pickle.pyc in _batch_setitems(self, items)
661 for k, v in items:
662 save(k)
--> 663 save(v)
664 write(SETITEM)
665 return
/usr/lib/python2.7/pickle.pyc in save(self, obj)
304 reduce = getattr(obj, "__reduce_ex__", None)
305 if reduce:
--> 306 rv = reduce(self.proto)
307 else:
308 reduce = getattr(obj, "__reduce__", None)
/usr/lib/python2.7/copy_reg.pyc in _reduce_ex(self, proto)
75 except AttributeError:
76 if getattr(self, "__slots__", None):
---> 77 raise TypeError("a class that defines __slots__ without "
78 "defining __getstate__ cannot be pickled")
79 try:
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled
Re: multiprocessing & HTTPConnection
Verfasst: Montag 1. September 2014, 10:31
von Boa
BlackJack hat geschrieben:@Boa: Also ich kann keine *bestehende* Verbindung serialisieren, nur unverbundene `HTTPConnection`\s:
Ah Danke, gut zu wissen. Dann lasse ich das sein.