'concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.' 에러 Troubleshooting

김동욱·2024년 1월 19일
0

Troubleshooting

목록 보기
4/14
post-thumbnail

문제 상황

개발 중 대량의 데이터가 적재된 파일들을 읽어서 찾고자 하는 키워드가 포함된 라인 수를 세는 로직을 개발하게 됐다. 하나의 파일에는 대략 3천만 ~ 5천만 라인의 데이터가 있어 하나의 파일을 읽어드리는데도 약 20초의 시간이 소요됐다. 하지만 이러한 파일들의 수가 많았기 때문에, 기존에 모두 순차적으로 읽어드리는 방식에서 멀티 프로세스를 사용하여 병렬로 처리하도록 로직을 아래와 같이 바꿨다.

    try:
        files = os.listdir(path_to_search)
    except FileNotFoundError:
        raise FileNotFoundException({"message": "설정 파일을 찾을 수 없습니다."})

    pool = concurrent.futures.ProcessPoolExecutor(max_workers=len(files))

    procs = []
    for month in range(start_month, end_month + 1):
        file_name = 'gcp_tm.' + str(month)
        if file_name in files:
            procs.append(pool.submit(count_keyword_from_file, file_name, keyword, path_to_search))

    total_count = 0
    for p in concurrent.futures.as_completed(procs):
        total_count += p.result()

별 문제가 없어보이는 로직이지만 아래와 같은 에러가 발생했다. 실행 중이거나 대기 중에 프로세스 pool의 프로세스가 갑자기 종료 됐다고 한다. 처음엔 max_workers의 수 때문에 일 수도 있다는 글을 참고하여 변경해 보았지만 동일한 에러가 발생했다.

concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

해결 방법

해당 글을 보고 문제를 해결했다. 해당 글에선 Django에서 멀티프로세싱 사용 시, 애플리케이션, 모델 및 기타 구성 요소가 모두 로드 되도록 하려면 각 하위 프로세스에서 Django 애플리케이션을 초기화 하라고 한다. django.setup을 사용하여 pool을 초기화 해야한다고 한다. 아래와 같이 수정하여 문제를 해결할 수 있었다.

concurrent.futures.ProcessPoolExecutor(max_workers=len(files), initializer=django.setup)

Django 프로젝트에서 멀티프로세싱을 사용할 때 각 하위 프로세스에서 Django의 설정과 앱을 올바르게 초기화하는 것은 중요하다. 그렇지 않으면, 모델이나 다른 Django 구성 요소에 대한 참조가 올바르게 해석되지 않아 예기치 않은 동작이나 에러가 발생할 수 있다.

initializer 매개변수와 django.setup() 함수를 사용하여 ProcessPoolExecutor의 각 프로세스가 시작될 때 Django 환경을 초기화하는 것은 이러한 문제를 방지할 수 있다.

django.setup()은 Django의 설정을 구성하고 앱을 로드하는 함수로, 보통 Django 프로젝트의 WSGI 또는 ASGI 애플리케이션에서 호출된다. 앞서 말했 듯, 멀티프로세싱 환경에서 Django 모델이나 기타 구성 요소를 사용하려면 각 하위 프로세스에서도 Django 환경이 올바르게 설정되어 있어야 하기 때문에, initializer 매개변수를 사용하여 ProcessPoolExecutor에게 각 프로세스가 시작될 때 django.setup()을 호출하도록 지시할 수 있다.

이 방법을 사용하면 각 하위 프로세스에서 Django 애플리케이션과 모델이 올바르게 초기화되어, 멀티프로세싱 환경에서도 Django의 기능을 안정적으로 사용할 수 있다.








참고 자료

https://copyprogramming.com/howto/django-how-can-i-use-multiprocessing-in-a-management-command#django-how-can-i-use-multiprocessing-in-a-management-command

profile
안녕하세요! 질문과 피드백은 언제든지 환영입니다:)

0개의 댓글