w3_pool_queue - steelbear/HMG_Softeer_DE GitHub Wiki
๋ฌธ์
ํ์ด์ฌ ๊ณต์ ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด, Queue๋ ํ๋ก์ธ์ค๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋ ๊ฐ์ฒด์ ํ๋๋ก Process์๊ฒ ์ ๋ฌํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
if __name__ == '__main__':
queue = Queue()
p1 = Process(work, (queue, ))
p2 = Process(work, (queue, ))
p1.start()
p2.start()
print(queue.get())
print(queue.get())
p1.join()
p2.join()
์์ ์ฝ๋์์ ๊ฐ ํ๋ก์ธ์ค๊ฐ queue์๊ฒ ์ด๋ค ๊ฐ์ ์ง์ด๋ฃ์๋ค๋ฉด ๋ฉ์ธ ํ๋ก์ธ์ค์์ ์ด๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
ํ์ง๋ง ์ด๋ Pool์์๋ ๊ทธ๋๋ก ์ํํ ์ ์์ต๋๋ค.
if __name__ == '__main__':
queue = Queue()
with Pool(2) as p:
p.apply(work, (queue, ))
๋ค์์ ์คํํ๋ฉด ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
RuntimeError: Queue objects should only be shared between processes through inheritance
๊ทธ๋ ๋ค๋ฉด Process์ ์ ๋ฐ์๋ Queue๋ฅผ Pool์ ์ ๋ฐ์ ์ ์์๊น์?
Pool์ ์ธ์๋ฅผ pickling ํ๋ค
def apply(self, func, args=(), kwds={}):
'''
Equivalent of `func(*args, **kwds)`.
Pool must be running.
'''
return self.apply_async(func, args, kwds).get()
def apply_async(self, func, args=(), kwds={}, callback=None,
error_callback=None):
'''
Asynchronous version of `apply()` method.
'''
self._check_running()
result = ApplyResult(self, callback, error_callback)
self._taskqueue.put(([(result._job, 0, func, args, kwds)], None))
return result
๋ค์ ์ฝ๋๋ Pool.apply์ Pool.apply_async์ ๊ตฌํ ์ฝ๋์ ๋๋ค. ์ฝ๋์์๋ func์ args, kwds ๋ชจ๋ self._taskqueue์ ์ง์ด๋ฃ๋๋ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
class Pool(object):
'''
Class which supports an async version of applying functions to arguments.
'''
_wrap_exception = True
@staticmethod
def Process(ctx, *args, **kwds):
return ctx.Process(*args, **kwds)
def __init__(self, processes=None, initializer=None, initargs=(),
maxtasksperchild=None, context=None):
# Attributes initialized early to make sure that they exist in
# __del__() if __init__() raises an exception
self._pool = []
self._state = INIT
self._ctx = context or get_context()
self._setup_queues()
self._taskqueue = queue.SimpleQueue()
๊ทธ๋ฆฌ๊ณ self._taskqueue๋ SimpleQueue ๊ฐ์ฒด์ ๋๋ค.
๊ทธ๋ ๋ค๋ฉด SimpleQueue๊ฐ ์ด๋ป๊ฒ ์ ์ฅํ๋์ง๋ฅผ ํ์ธํด๋ด ์๋ค.
def put(self, obj):
# serialize the data before acquiring the lock
obj = _ForkingPickler.dumps(obj)
if self._wlock is None:
# writes to a message oriented win32 pipe are atomic
self._writer.send_bytes(obj)
else:
with self._wlock:
self._writer.send_bytes(obj)
SimpleQueue.put์ ๊ตฌํ ์ฝ๋๋ฅผ ๋ณด๋ฉด _ForkingPickler.dumps๋ฅผ ํตํด ๋ฐ์ obj ์ ์ฒด๋ฅผ pickling ํฉ๋๋ค.
์ฌ๊ธฐ์ obj์๋ func ๋ฟ๋ง ์๋๋ผ args ๋ชจ๋ ํฌํจ๋์ด์์ด pickling์ด ๋๋ค๋ ๊ฒ์ ํ์ธํ์ต๋๋ค.
์ฆ, Pool.apply๋ฅผ ํตํด Queue๋ฅผ ์ ๋ฌํ๋ฉด Queue ๊ฐ์ฒด๊ฐ pickling ๋๊ธฐ์ ์ด๋ฅผ ๋ง๊ธฐ์ํด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Manager ๊ฐ์ฒด๋ฅผ ํตํด pickling ๋๋๋ผ๋ ์๋ณธ ๊ฐ์ฒด์ ์ ๊ทผํ ์ ์๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.