2014-07-15 3 views
0
logging 모듈 핸들러와 multiprocessing 작업을 함께 사용하지 않는 것 같다

를 제기 다음 메서드 중 오류가 발생하지 않습니다.파이썬 멀티 logging.FileHandler 객체는 PicklingError

# this works 
def pWorker(x) : 
    worker(x, handler) 

# this works too 
pWorker = functools.partial(worker, handler=open('logFile')) 

나는 PicklingError을 정말로 이해하지 못합니다. 클래스 logging.FileHandler의 오브젝트를 선택 할 수 없기 때문입니까? (내가 봤지만 아무것도 찾지 못했습니다)

답변

1

FileHandler 개체는 내부적으로 threading.Lock을 사용하여 스레드 간의 쓰기를 동기화합니다. 그러나 에 의해 반환 된 thread.lock 개체는 피클 할 수 없습니다. 이는 프로세스간에 전송 될 수 없음을 의미합니다.이 프로세스는 pool.map을 통해 하위 프로세스로 전송해야합니다.

multiprocessing 문서에는 multiprocessing과 함께 로깅을 수행하는 방법에 대해 설명하는 섹션이 있습니다. here. 기본적으로 자식 프로세스가 map 호출을 통해 로거 또는 처리기를 명시 적으로 전달하는 대신 부모 프로세스의 로거를 상속해야합니다.

참고하지만, 그 리눅스에서, 당신은이 작업을 수행 할 수 있습니다

from multiprocessing import Pool 
import logging 

logger = logging.getLogger('myLogger') 


def worker(x): 
    print handler 
    print x **2 

def initializer(handle): 
    global handler 
    handler = handle 

if __name__ == "__main__": 
    handler = logging.FileHandler('logFile') 
    #pWorker = functools.partial(worker, handler=handler) 
    pool = Pool(processes=4, initializer=initializer, initargs=(handler,)) 
    pool.map(worker, range(3)) 
    pool.close() 
    pool.join 

initializer/initargs는 즉시 시작으로 풀의 자식 프로세스의 각 한 번 방법을 실행하는 데 사용됩니다. 리눅스에서는 이것은 os.fork이 작동하는 덕분에 상속을 통해 핸들러를 자식으로 가질 수 있습니다. 그러나, this won't work on Windows; os.fork에 대한 지원이 부족하기 때문에 initargs을 통해 전달하려면 handler 피클해야합니다.