Sie könnten über keys()
iterieren, um Ihren Speicherbedarf zu reduzieren. Du musst dich davor schützen, dass Schlüssel gelöscht werden.
Ansonsten ist hier ein Beispiel mit zwei verschiedenen Möglichkeiten, mit denen Sie die Elemente in einem Diktat durchlaufen können. Die Methode iteritems()
in diesem Beispiel funktioniert nur vom Prozess, der das Manager-Objekt und den untergeordneten Prozess erstellt, die das Manager-Objekt erstellt. Dies liegt daran, dass das Manager-Objekt zum Erstellen neuer Proxys benötigt wird und andere Prozesse keinen Zugriff darauf haben. Die Methode iteritems2()
funktioniert von anderen Prozessen, da sie nicht darauf angewiesen ist, in diesen Prozessen einen neuen Proxy zu erstellen.
import multiprocessing as mp
import multiprocessing.managers
class mydict(dict):
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
self.iters = {}
def iteritems(self):
print "iteritems", mp.current_process()
return dict.iteritems(self)
def _iteritems_start(self):
print "_iteritems_start", mp.current_process()
i = dict.iteritems(self)
self.iters[id(i)] = i
return id(i)
def _iteritems_next(self, iter_id):
try:
return self.iters[iter_id].next()
except StopIteration:
del self.iters[iter_id]
return None
class mydict_proxy(mp.managers.DictProxy):
def iteritems(self):
print "iteritems proxy", mp.current_process()
return self._callmethod("iteritems")
def iteritems2(self):
print "iteritems2 proxy", mp.current_process()
iter_id = self._callmethod("_iteritems_start")
def generator():
while True:
a = self._callmethod("_iteritems_next",
(iter_id,))
if a == None:
return
yield a
return generator()
_method_to_typeid_ = { "iteritems": "Iterator" }
_exposed_ = mp.managers.DictProxy._exposed_
_exposed_ += ("iteritems", "_iteritems_start", "_iteritems_next")
class mymanager(mp.managers.BaseManager):
pass
mymanager.register("mydict", mydict, mydict_proxy)
mymanager.register("Iterator", proxytype = mp.managers.IteratorProxy,
create_method = False)
def other(d):
for k, v in d.iteritems2():
d[k] = v.lower()
for k, v in d.iteritems():
d[k] = ord(v)
def main():
manager = mymanager()
manager.start()
d = manager.mydict(list(enumerate("ABCDEFGHIJKLMNOP")))
for (k, v) in d.iteritems():
print k, v
proc = mp.Process(target = other, args = (d,))
proc.start()
proc.join()
for (k, v) in d.iteritems():
print k, v
if __name__ == "__main__":
main()
Beachten Sie, dass während dieser Code mehr Speicher effizient sein kann, es ist wahrscheinlich ein Heck viel langsamer zu gehen.
Haben Sie erwogen, 'SyncManager' zu verwenden und registrieren Sie dort Ihren eigenen Proxy mit' iseritems' exponiert? – oleg
@oleg Sie können iteritems nicht einfach verfügbar machen, da die zurückgegebenen dict-Iteratoren nicht auswählbar sind. Das ist der Grund, warum der Standard-dict-Proxy ihn und damit die Frage nicht offen legt. – otus
Ich sagte nicht "einfach" aussetzen. :) Können wir 'IteratorProxy' verwenden, um' iteritems' freizulegen? – oleg