본문 바로가기
카테고리 없음

Python의 프로세스 종류와 동작 및 시작 방식

by 브링블링 2024. 12. 10.
반응형

Python의 프로세스 종류와 동작 및 시작 방식

Python의 multiprocessing 모듈은 프로세스를 생성하고 관리하기 위한 강력한 도구를 제공합니다. 이 글에서는 Python의 프로세스 종류와 동작 방식을 이해하고, 시작 방식에 대해서 정리했습니다.

시작 방식 특징 지원 플랫폼 사용 사례
spawn 새로운 Python 인터프리터 프로세스 생성 Windows, macOS, Unix 안전성 요구 작업
fork 부모 프로세스를 복제 Unix 계열 속도와 효율성 중시 작업
forkserver 별도의 포크 서버를 통해 프로세스 생성 Unix 계열 fork보다 안전성 높은 작업

 


1. 프로세스 종류

Python에서는 두 가지 주요 프로세스 유형이 있습니다:

  1. 메인 프로세스 (Main Process):
    •    Python 스크립트를 실행하면 기본적으로 메인 프로세스가 생성됩니다.
    •    모든 서브프로세스의 부모 역할을 하며, 프로그램의 진입점입니다.
  2. 서브프로세스 (Subprocess):
    •   메인 프로세스에서 생성된 프로세스로, 작업을 병렬로 수행합니다.
    •   독립적인 메모리 공간을 가지며, 다른 서브프로세스와 직접적으로 공유되지 않습니다.

2. 프로세스 동작 방식

  1. 독립적인 메모리 공간:
    •   각 프로세스는 독립적인 메모리 공간을 가지며, 데이터는 기본적으로 공유되지 않습니다.
    •   데이터 공유가 필요하면 Queue, Pipe, Value 또는 Array 같은 도구를 사용합니다.
  2. GIL(Global Interpreter Lock) 우회:
    •   멀티스레딩은 GIL의 제약을 받지만, 멀티프로세싱은 각 프로세스가 별도의 Python 인터프리터를 실행하므로 GIL의 영향을 받지 않습니다.
  3. 병렬 실행:
    •   멀티코어 CPU를 활용하여 여러 프로세스가 병렬로 작업을 수행합니다.

3. 프로세스 시작 방식

Python의 multiprocessing 모듈은 운영 체제에 따라 다음 세 가지 프로세스 시작 방식을 지원합니다:

  1. spawn (생성):
    •   새로운 Python 인터프리터 프로세스를 생성합니다.
    •   부모 프로세스의 상태는 복제되지 않으며, 필요한 객체는 직렬화(피클링)를 통해 전달됩니다.
    •   Windows 및 macOS의 기본 방식.
    •   특징:
      •   더 안전하지만 속도가 느림.
      •   데이터 직렬화가 필요.
  2. fork (복제):
    •   부모 프로세스를 그대로 복제하여 새로운 프로세스를 생성합니다.
    •   Unix 계열에서 기본 방식.
    •   특징:
      •   빠르고 메모리 효율적.
      •   부모 프로세스의 모든 자원을 복제하므로, 스레드 안전 문제가 발생할 수 있음.
  3. forkserver:
    •   별도의 포크 서버 프로세스를 시작하여 새로운 프로세스를 생성합니다.
    •   특징:
      •   fork의 장점(속도와 효율성)을 유지하면서 더 안전함.
      •   Unix 계열에서만 사용 가능.

반응형

4. 단계별 설명 및 예제 코드

단계 1: 기본 프로세스 생성 (spawn 방식)

import multiprocessing
import os

def worker_function(name):
    print(f"Worker {name} is running in process {os.getpid()}")

if __name__ == "__main__":
    multiprocessing.set_start_method("spawn")  # spawn 방식 설정
    print(f"Main process ID: {os.getpid()}")

    # 서브프로세스 생성
    process1 = multiprocessing.Process(target=worker_function, args=("A",))
    process2 = multiprocessing.Process(target=worker_function, args=("B",))

    process1.start()
    process2.start()

    process1.join()
    process2.join()

    print("Main process finished")

 

출력 예시:

Main process ID: 12345
Worker A is running in process 12346
Worker B is running in process 12347
Main process finished

단계 2: fork 방식 (Unix 계열에서만)

import multiprocessing
import os

def worker_function(name):
    print(f"Worker {name} is running in process {os.getpid()}")

if __name__ == "__main__":
    multiprocessing.set_start_method("fork")  # fork 방식 설정
    print(f"Main process ID: {os.getpid()}")

    process = multiprocessing.Process(target=worker_function, args=("Task",))
    process.start()
    process.join()

    print("Main process finished")

 

출력 예시 (Unix 계열에서만 실행 가능):

Main process ID: 12345
Worker Task is running in process 12346
Main process finished

단계 3: forkserver 방식

import multiprocessing
import os

def worker_function(name):
    print(f"Worker {name} is running in process {os.getpid()}")

if __name__ == "__main__":
    multiprocessing.set_start_method("forkserver")  # forkserver 방식 설정
    print(f"Main process ID: {os.getpid()}")

    process = multiprocessing.Process(target=worker_function, args=("Task",))
    process.start()
    process.join()

    print("Main process finished")

 

출력 예시:

Main process ID: 12345
Worker Task is running in process 12346
Main process finished

단계 4: 프로세스 간 통신

Queue를 사용하여 프로세스 간 데이터를 교환하는 예제입니다.

import multiprocessing

def worker(queue):
    queue.put("Data from worker")

if __name__ == "__main__":
    multiprocessing.set_start_method("spawn")  # spawn 방식 설정
    queue = multiprocessing.Queue()

    process = multiprocessing.Process(target=worker, args=(queue,))
    process.start()
    process.join()

    # Queue에서 데이터 읽기
    print(f"Received from worker: {queue.get()}")

 

출력 예시:

Received from worker: Data from worker
반응형