Python 프로세스 풀 비 데모닉?
데모닉이 아닌 파이썬 풀을 만들 수 있습니까? 풀이 내부에 다른 풀이있는 함수를 호출 할 수 있기를 원합니다.
데몬 프로세스는 프로세스를 만들 수 없기 때문에 이것을 원합니다. 특히 다음과 같은 오류가 발생합니다.
AssertionError: daemonic processes are not allowed to have children
예를 들어, function_a
를 실행하는 풀이있는 실행 function_b
중인 풀이있는 시나리오를 고려하십시오 function_c
. 이 함수 체인은 function_b
데몬 프로세스에서 실행되고 있기 때문에 실패 하고 데몬 프로세스는 프로세스를 만들 수 없습니다.
multiprocessing.pool.Pool
클래스는에서 작업자 프로세스 생성 __init__
악마의를하게하고이를 시작 방법을, 그리고 자신의-다시 설정 할 수 없습니다 daemon
에 속성을 False
가 시작된다 (그리고 나중에 그것이 더 이상 허용하지 않는다) 전에. 그러나 multiprocesing.pool.Pool
( multiprocessing.Pool
은 래퍼 함수일뿐입니다)의 고유 한 multiprocessing.Process
하위 클래스를 만들고 작업자 프로세스에 사용할 수 있도록 항상 비 데모닉 인 자체 하위 클래스로 대체 할 수 있습니다.
다음은이를 수행하는 방법에 대한 전체 예입니다. 중요한 부분은 두 개의 클래스입니다 NoDaemonProcess
및 MyPool
상단 및 호출 pool.close()
하고 pool.join()
온 MyPool
끝에 인스턴스입니다.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import multiprocessing
# We must import this explicitly, it is not imported by the top-level
# multiprocessing module.
import multiprocessing.pool
import time
from random import randint
class NoDaemonProcess(multiprocessing.Process):
# make 'daemon' attribute always return False
def _get_daemon(self):
return False
def _set_daemon(self, value):
pass
daemon = property(_get_daemon, _set_daemon)
# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(multiprocessing.pool.Pool):
Process = NoDaemonProcess
def sleepawhile(t):
print("Sleeping %i seconds..." % t)
time.sleep(t)
return t
def work(num_procs):
print("Creating %i (daemon) workers and jobs in child." % num_procs)
pool = multiprocessing.Pool(num_procs)
result = pool.map(sleepawhile,
[randint(1, 5) for x in range(num_procs)])
# The following is not really needed, since the (daemon) workers of the
# child's pool are killed when the child is terminated, but it's good
# practice to cleanup after ourselves anyway.
pool.close()
pool.join()
return result
def test():
print("Creating 5 (non-daemon) workers and jobs in main process.")
pool = MyPool(5)
result = pool.map(work, [randint(1, 5) for x in range(5)])
pool.close()
pool.join()
print(result)
if __name__ == '__main__':
test()
멀티 프로세싱 모듈은 프로세스와 풀을 사용하기 좋은 인터페이스를 가지고 또는 스레드. 현재 사용 사례 multiprocessing.pool.ThreadPool
에 따라 외부 풀에 사용 하는 것을 고려할 수 있습니다. 그러면 프로세스가 아닌 스레드 (내부에서 프로세스를 생성 할 수있는)가 생성 됩니다.
GIL에 의해 제한 될 수 있지만, 제 특별한 경우 (둘 다 테스트했습니다) , 여기서Pool
생성 된 외부 프로세스의 시작 시간 이 .ThreadPool
그것은 스왑 정말 쉽습니다 Processes
위한 Threads
. 여기 또는 여기 에서 ThreadPool
솔루션 사용 방법에 대해 자세히 알아보십시오 .
Python 3.7에서 데모닉이 아닌 풀을 사용해야 할 필요성이 있었고 수락 된 답변에 게시 된 코드를 수정했습니다. 아래는 비 데모닉 풀을 생성하는 스 니펫입니다.
class NoDaemonProcess(multiprocessing.Process):
@property
def daemon(self):
return False
@daemon.setter
def daemon(self, value):
pass
class NoDaemonContext(type(multiprocessing.get_context())):
Process = NoDaemonProcess
# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(multiprocessing.pool.Pool):
def __init__(self, *args, **kwargs):
kwargs['context'] = NoDaemonContext()
super(MyPool, self).__init__(*args, **kwargs)
의 현재 구현이 multiprocessing
컨텍스트를 기반으로하도록 광범위하게 리팩토링되었으므로 as 속성 NoDaemonContext
이 있는 클래스 를 제공해야 NoDaemonProcess
합니다. MyPool
그러면 기본 컨텍스트 대신 해당 컨텍스트를 사용합니다.
즉,이 접근 방식에 대해 최소한 두 가지주의 사항이 있음을 경고해야합니다.
- 여전히
multiprocessing
패키지 의 구현 세부 사항에 따라 다르 므로 언제든지 중단 될 수 있습니다. multiprocessing
데모닉이 아닌 프로세스를 사용하기 어렵게 만든 타당한 이유 가 있습니다 . 그 중 많은 부분이 여기 에 설명되어 있습니다 . 제 생각에 가장 설득력있는 것은 :As for allowing children threads to spawn off children of its own using subprocess runs the risk of creating a little army of zombie 'grandchildren' if either the parent or child threads terminate before the subprocess completes and returns.
The issue I encountered was in trying to import globals between modules, causing the ProcessPool() line to get evaluated multiple times.
globals.py
from processing import Manager, Lock
from pathos.multiprocessing import ProcessPool
from pathos.threading import ThreadPool
class SingletonMeta(type):
def __new__(cls, name, bases, dict):
dict['__deepcopy__'] = dict['__copy__'] = lambda self, *args: self
return super(SingletonMeta, cls).__new__(cls, name, bases, dict)
def __init__(cls, name, bases, dict):
super(SingletonMeta, cls).__init__(name, bases, dict)
cls.instance = None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance = super(SingletonMeta, cls).__call__(*args, **kw)
return cls.instance
def __deepcopy__(self, item):
return item.__class__.instance
class Globals(object):
__metaclass__ = SingletonMeta
"""
This class is a workaround to the bug: AssertionError: daemonic processes are not allowed to have children
The root cause is that importing this file from different modules causes this file to be reevalutated each time,
thus ProcessPool() gets reexecuted inside that child thread, thus causing the daemonic processes bug
"""
def __init__(self):
print "%s::__init__()" % (self.__class__.__name__)
self.shared_manager = Manager()
self.shared_process_pool = ProcessPool()
self.shared_thread_pool = ThreadPool()
self.shared_lock = Lock() # BUG: Windows: global name 'lock' is not defined | doesn't affect cygwin
Then import safely from elsewhere in your code
from globals import Globals
Globals().shared_manager
Globals().shared_process_pool
Globals().shared_thread_pool
Globals().shared_lock
On some Python versions replacing standart Pool to custom can raise error: AssertionError: group argument must be None for now
.
Here I found a solution that can help:
class NonDaemonPool(multiprocessing.pool.Pool):
def Process(self, *args, **kwds):
proc = super(NonDaemonPool, self).Process(*args, **kwds)
class NonDaemonProcess(proc.__class__):
"""Monkey-patch process to ensure it is never daemonized"""
@property
def daemon(self):
return False
@daemon.setter
def daemon(self, val):
pass
proc.__class__ = NonDaemonProcess
return proc
참고URL : https://stackoverflow.com/questions/6974695/python-process-pool-non-daemonic
'Development Tip' 카테고리의 다른 글
내 암호를 심볼릭 링크 된 디렉토리의 실제 경로로 어떻게 변경합니까? (0) | 2020.10.16 |
---|---|
"연산자 bool () const"의 의미는 무엇입니까? (0) | 2020.10.16 |
누락 된 값을 더 간결하게 찾으려면 어떻게해야합니까? (0) | 2020.10.15 |
VS 2012 RC에서 사용자 유형 C # 구문 강조 표시가 다시 작동하도록하려면 어떻게해야합니까? (0) | 2020.10.15 |
부트 스트랩 중심 제목 (0) | 2020.10.15 |