keys()
을 반복하여 메모리 사용 공간을 줄일 수 있습니다. 키가 삭제되지 않도록주의해야합니다.
그렇지 않은 경우 다음은 두 가지 방법으로 예제를 작성하는 예제입니다.이 두 가지 방법을 통해 사전에있는 항목을 반복 할 수 있습니다. 이 예의 iteritems()
메서드는 관리자 개체를 만드는 프로세스와 관리자 개체가 만드는 자식 프로세스에서만 작동합니다. 이는 관리자 객체가 새 프록시를 만드는 데 필요하고 다른 프로세스는 프록시에 액세스 할 수 없기 때문입니다. iteritems2()
메서드는 해당 프로세스에서 새 프록시를 만드는 데 의존하지 않으므로 다른 프로세스에서 작동합니다.
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()
이 코드는 메모리 효율이 높지만 아마도 느린 속도 일 수 있습니다.
당신은'SyncManager'를 사용하고'iteritems'가 노출 된 자신의 프록시를 등록했다고 생각 했습니까? – oleg
@oleg iterators가 리턴하는 dict iterator는 pickleable이 아니기 때문에 단순히 iteritem을 노출 할 수는 없습니다. 그게 기본 dict 프록시가 그것을 노출하고 따라서 질문을 노출하지 않는 이유입니다. – otus
나는 "간단하게"폭로한다고 말하지 않았다. :)'iteritems'을 노출하기 위해'IteratorProxy'를 사용할 수 있습니까? – oleg