2012-04-09 4 views
1

Ich versuche, die Multiprocessing-Pool-Klasse zu verwenden, um eine reine Funktion über einige unveränderliche Objekte abzubilden. Wenn ich jedoch versuche, dies auszuführen, sehe ich eine Menge Fehler im Terminal (manchmal für Minuten), und oft muss Python "auf ungewöhnliche Weise beendet werden". Ich benutze Windows (XP) mit Python 3.2.2.Fehler beim Verwenden von multiprocessing.pool-Map beim Lesen von einem unveränderlichen Objekt

import multiprocessing 

def do_stuff(v): 
    return v.x + v.y 

class Vector: 
    __slots__ = ['x', 'y'] 

    def __setattr__(self, name, value): 
     raise AttributeError("Cannot assign values to object {0} of type {1}".format(self, type(self))) 

    def __init__(self, x, y = None): 
     """Initialize an immutable x, y Vector""" 
     object.__setattr__(self, 'x', x) 
     object.__setattr__(self, 'y', y) 

if __name__ == "__main__": 
    todo = [Vector(1, 2), Vector(3, 4), Vector(-1, 12), Vector(16, 32), Vector(16, 32)] 
    pool = multiprocessing.Pool(4) 
    results = list(pool.map(do_stuff, todo)) 
    print(results) 

Erwartete Ausgabe:

[3, 7, 11, 48, 48] 

Die Anzahl der Fehler ist sehr groß, aber es scheint, bis auf etwas in pool.map zu kochen versuchen Attribute auf einem Vektor zu setzen:

Process PoolWorker-1: 
Traceback (most recent call last): 
    File "c:\Python32\lib\multiprocessing\process.py", line 267, in _bootstrap 
Process PoolWorker-2: 
Traceback (most recent call last): 
    File "c:\Python32\lib\multiprocessing\process.py", line 267, in _bootstrap 
    self.run() 
    File "c:\Python32\lib\multiprocessing\process.py", line 116, in run 
    self._target(*self._args, **self._kwargs) 
    File "c:\Python32\lib\multiprocessing\pool.py", line 102, in worker 
    task = get() 
    File "c:\Python32\lib\multiprocessing\queues.py", line 378, in get 
    return recv() 
    File "d:\Documents and Settings\Userdir\Scripts\temp\test.py", line 11, in __s 
etattr__ 
    raise AttributeError("Cannot assign values to object {0} of type {1}".format 
(self, type(self))) 
AttributeError: Cannot assign values to object <__main__.Vector object at 0x00C2 
BBB0> of type <class '__main__.Vector'> 

Ich kann die Zeile auskommentieren beginnend mit __slots__ (seltsam?), Verwenden Sie eine reguläre map, oder ich kann die Vector-Klasse veränderbar machen (Kommentar aus der __setattr__), und jeder von diesen selbst wird dazu führen, dass es gut funktioniert.

Warum sollte irgendetwas versuchen, Attribute auf meine Objekte zu setzen, wenn alles, was ich gerade mache, von den Objekten liest?

Warum wird das Entfernen von __slots__ aus dem Objekt verursachen dies ordnungsgemäß funktioniert?

EDIT:

Ich verwende __slots__ als eine Möglichkeit, Speicher/Platzersparnis, da es in der Regel eine große Anzahl von Vektoren in meinem Programm. So kann ich nicht Vektor stammt aus einem Tupel: __slots__ do not work for classes derived from ''variable-length'' built-in types such as long, str and tuple

+0

Gibt es einen alternativen Weg, um eine Klasse unveränderlich zu machen, die für dieses Szenario funktioniert? – Darthfett

+0

'__slots__' ist da, um Speicherplatz mit einer großen Anzahl von Vektoren zu sparen. – Darthfett

+0

Ahh, ich dachte, du würdest annehmen, dass der Zweck von '__slots__' darin bestünde, Vector unveränderlich zu machen. Es löst das Problem, und ich könnte Ihre Antwort akzeptieren, wenn es als eins gepostet wurde. :) Vielen Dank! – Darthfett

Antwort

1

__slots__ Ursachen Unpickling Probleme mit multiprocessing, siehe zum Beispiel python multiprocessing pickle protocol

Da Sie es nicht brauchen für Unveränderlichkeit (Ihre __setattr__ ist ausreichend für alle praktischen Zwecke) Ich schlage vor, du entfernst es.

Wenn Sie es wirklich brauchen Platz zu sparen, implementieren dann __getstate__ und __setstate__, die das Unpickling Problem beheben könnte.

+1

Ich denke, das Problem, das ich hatte, war, dass ich nicht wusste, dass es die Objekte beizen war. Laut der Dokumentation hierzu: "Zur Zeit der Unpickling können einige Methoden wie __getattr __(), __getattribute __() oder __setattr __() für die Instanz aufgerufen werden." Um dieses Problem zu umgehen, musste ich also die Funktionen für den get/set-Status definieren. Es war kein Problem, dass '__slots__' nicht mit Multiprocessing arbeitet. – Darthfett

Verwandte Themen