functools.partial() und multiprocessing

29/09/2011 - 13:32 von Tobias Klausmann | Report spam
Moin!

Ich arbeite derzeit mit partial() und dem multiprocessing-Modul.
Unter 2.7 und 3.2 ist alles rosig. Dummerweise muss das Skript
auch mit 2.6.5 laufen.

Trivialbeispiel:
from functools import partial
from multiprocessing import Pool

def fun(a, b):
return a+b

fun2=partial(fun, b=2)
pool = Pool(5)
results = pool.map(fun2, range(1))

print len(results)

Das liefert, wie zu erwarten, "1", wenn man 2.7.x oder 3.2.x
benuztzt.

Damit es echtes multiprocessing wird, kann man auch range(100)
benutzen, am Problem àndert sich nichts (nur wird der stacktrace
unübersichtlich).

Mit 2.6.5 passiert das hier:

Process PoolWorker-1:
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 "/usr/lib/python2.6/multiprocessing/pool.py", line 57, in worker
task = get()
File "/usr/lib/python2.6/multiprocessing/queues.py", line 352, in get
return recv()
TypeError: type 'partial' takes at least one argument

Und das Programm terminiert auch nicht.

Mir ist nicht ganz klar, ob ich partial/multiprocessing nur
falsch benutze oder das, was ich will, mit 2.6.5 einfach nicht
geht. Das Problem ohne partial() zu lösen ginge auch, wàre aber
deutlich hàsslicher.

Gruss,
Tobias
 

Lesen sie die antworten

#1 Peter Otten
29/09/2011 - 15:32 | Warnen spam
Tobias Klausmann wrote:

Moin!

Ich arbeite derzeit mit partial() und dem multiprocessing-Modul.
Unter 2.7 und 3.2 ist alles rosig. Dummerweise muss das Skript
auch mit 2.6.5 laufen.

Trivialbeispiel:
from functools import partial
from multiprocessing import Pool

def fun(a, b):
return a+b

fun2=partial(fun, b=2)
pool = Pool(5)
results = pool.map(fun2, range(1))

print len(results)

Das liefert, wie zu erwarten, "1", wenn man 2.7.x oder 3.2.x
benuztzt.

Damit es echtes multiprocessing wird, kann man auch range(100)
benutzen, am Problem àndert sich nichts (nur wird der stacktrace
unübersichtlich).

Mit 2.6.5 passiert das hier:

Process PoolWorker-1:
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 "/usr/lib/python2.6/multiprocessing/pool.py", line 57, in worker
task = get()
File "/usr/lib/python2.6/multiprocessing/queues.py", line 352, in get
return recv()
TypeError: type 'partial' takes at least one argument

Und das Programm terminiert auch nicht.

Mir ist nicht ganz klar, ob ich partial/multiprocessing nur
falsch benutze oder das, was ich will, mit 2.6.5 einfach nicht
geht. Das Problem ohne partial() zu lösen ginge auch, wàre aber
deutlich hàsslicher.



Ich vermute, dass das Problem darin besteht, dass partial-Objekte erst ab
2.7 serialisierbar sind. Unterstützung für pickle làsst sich aber
nachrüsten:

from functools import partial
import copy_reg

def pickle_partial(p):
return unpickle_partial, (p.func, p.args, p.keywords)

def unpickle_partial(func, args, keywords):
return partial(func, *args, **keywords)

copy_reg.pickle(partial, pickle_partial)

Ähnliche fragen