[PYTHON] 프로세스간에 클래스를 공유하려면 어떻게해야합니까?
PYTHON프로세스간에 클래스를 공유하려면 어떻게해야합니까?
모든 프로세스가 최소한의 잠금으로 공유하고 업데이트하는 전역 개체를 갖고 싶습니다.
import multiprocessing
class Counter(object):
def __init__(self):
self.value = 0
def update(self, value):
self.value += value
def update(counter_proxy, thread_id):
counter_proxy.value.update(1)
print counter_proxy.value.value, 't%s' % thread_id, \
multiprocessing.current_process().name
return counter_proxy.value.value
def main():
manager = multiprocessing.Manager()
counter = manager.Value(Counter, Counter())
pool = multiprocessing.Pool(multiprocessing.cpu_count())
for i in range(10):
pool.apply(func = update, args = (counter, i))
pool.close()
pool.join()
print 'Should be 10 but is %s.' % counter.value.value
if __name__ == '__main__':
main()
결과는 10 점이 아니라 0 점입니다. 개체의 공유 값이 업데이트되지 않은 것 같습니다. 어떻게 이러한 값을 잠그고 업데이트 할 수 있습니까?
0 t0 PoolWorker-2
0 t1 PoolWorker-3
0 t2 PoolWorker-5
0 t3 PoolWorker-8
0 t4 PoolWorker-9
0 t5 PoolWorker-2
0 t6 PoolWorker-7
0 t7 PoolWorker-4
0 t8 PoolWorker-6
0 t9 PoolWorker-3
Should be 10 but is 0.
@dano에 의해 현재 최고의 솔루션 - 나는 클래스 프록시와 사용자 정의 관리자를 혼합.
import multiprocessing
from multiprocessing.managers import BaseManager, NamespaceProxy
class Counter(object):
def __init__(self):
self.value = 0
def update(self, value):
self.value += value
def update(counter_proxy, thread_id):
counter_proxy.update(1)
class CounterManager(BaseManager):
pass
class CounterProxy(NamespaceProxy):
_exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'update')
def update(self, value):
callmethod = object.__getattribute__(self, '_callmethod')
return callmethod(self.update.__name__, (value,))
CounterManager.register('Counter', Counter, CounterProxy)
def main():
manager = CounterManager()
manager.start()
counter = manager.Counter()
pool = multiprocessing.Pool(multiprocessing.cpu_count())
for i in range(10):
pool.apply(func = update, args = (counter, i))
pool.close()
pool.join()
print 'Should be 10 but is %s.' % counter.value
if __name__ == '__main__':
main()
해결법
-
==============================
1.다중 처리. 값은 사용자 정의 클래스와 함께 사용하도록 설계되지 않았으므로 다중 처리. 공유 유형과 유사해야합니다. 값. 대신 사용자 정의 관리자를 만들어 클래스를 등록해야합니다. 값을 직접 액세스하지 않고 기본적으로 클래스에 대해 생성 된 기본 프록시에서 내보내는 메소드를 통해 수정 / 액세스하면 인생도 더 쉬울 것입니다. 일반 특성 (예 : Counter.value)은 추가 사용자 지정없이 액세스 할 수 없습니다. 다음은 실제 예제입니다.
다중 처리. 값은 사용자 정의 클래스와 함께 사용하도록 설계되지 않았으므로 다중 처리. 공유 유형과 유사해야합니다. 값. 대신 사용자 정의 관리자를 만들어 클래스를 등록해야합니다. 값을 직접 액세스하지 않고 기본적으로 클래스에 대해 생성 된 기본 프록시에서 내보내는 메소드를 통해 수정 / 액세스하면 인생도 더 쉬울 것입니다. 일반 특성 (예 : Counter.value)은 추가 사용자 지정없이 액세스 할 수 없습니다. 다음은 실제 예제입니다.
import multiprocessing from multiprocessing.managers import BaseManager class MyManager(BaseManager): pass def Manager(): m = MyManager() m.start() return m class Counter(object): def __init__(self): self._value = 0 def update(self, value): self._value += value def get_value(self): return self._value MyManager.register('Counter', Counter) def update(counter_proxy, thread_id): counter_proxy.update(1) print counter_proxy.get_value(), 't%s' % thread_id, \ multiprocessing.current_process().name return counter_proxy def main(): manager = Manager() counter = manager.Counter() pool = multiprocessing.Pool(multiprocessing.cpu_count()) for i in range(10): pool.apply(func=update, args=(counter, i)) pool.close() pool.join() print 'Should be 10 but is %s.' % counter.get_value() if __name__ == '__main__': main()
산출:
1 t0 PoolWorker-2 2 t1 PoolWorker-8 3 t2 PoolWorker-4 4 t3 PoolWorker-5 5 t4 PoolWorker-6 6 t5 PoolWorker-7 7 t6 PoolWorker-3 8 t7 PoolWorker-9 9 t8 PoolWorker-2 10 t9 PoolWorker-8 Should be 10 but is 10.
from https://stackoverflow.com/questions/28612412/how-can-i-share-a-class-between-processes by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Pandas 데이터 프레임의 무작위 행 선택 (0) | 2018.11.26 |
---|---|
[PYTHON] 파이썬의 부분 일치 사전 키 (튜플 중) (0) | 2018.11.26 |
[PYTHON] 팬더 데이터 프레임의 음수를 0으로 대체하는 방법 (0) | 2018.11.26 |
[PYTHON] SciPy를 사용한 베 지어 커브 피팅 (0) | 2018.11.26 |
[PYTHON] OperationalError : (OperationalError) (2003, " '192.168.129.139'(111) '의 MySQL 서버에 연결할 수 없음) 없음 없음 (0) | 2018.11.26 |