- 하위 프로세스를 실행한느 방법
os.popen
os.exec
subprocess
subprocess
모듈 사용 권장- 관리 편의성 증대
import subprocess
result = subprocess.run(['echo', '자식 프로세스가 보내는 인사!'],
capture_output=True,
encoding='utf-8')
result.check_returncode() # 예외가 발생하지 않으면 문제없이 잘 종료한 것이다
print(result.stdout)
>>>
자식 프로세스가 보내는 인사!
run
함수로 프로세스 시작, 프로세스의 출력을 읽고 프로세스의 종료 여부 확인 가능subprocess
모듈을 통해 실행한 자식 프로세스는 부모 프로세스 파이선 인터프리터와 독립적으로 실행run
대신Popen
클래스를 사용한 자식 프로세스 실행 및 상태 검사 예제
proc = subprocess.Popen(['sleep', '1'])
while proc.poll() is None:
print('작업 중...')
# 시간이 걸리는 작업을 여기서 수행한다
...
print('종료 상태', proc.poll())
>>>
작업 중...
작업 중...
작업 중...
작업 중...
종료 상태 0
import time
start = time.time()
sleep_procs = []
for _ in range(10):
proc = subprocess.Popen(['sleep', '1'])
sleep_procs.append(proc)
for proc in sleep_procs:
proc.communicate()
end = time.time()
delta = end - start
print(f'{delta:.3} 초 만에 끝남')
>>>
1.04 초 만에 끝남
- PIPE 를 사용하여 하위 프로세스로 데이터를 보내거나 출력을 받을 수 있음
import os
def run_encrypt(data):
env = os.environ.copy()
env['password'] = 'zf7ShyBhZOraQDdE/FiZpm/m/8f9X+M1'
proc = subprocess.Popen(
['openssl', 'enc', '-des3', '-pass', 'env:password'],
env=env,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
proc.stdin.write(data)
proc.stdin.flush() # 자식이 입력을 받도록 보장한다
return proc
rocs = []
for _ in range(3):
data = os.urandom(10)
proc = run_encrypt(data)
procs.append(proc)
for proc in procs:
out, _ = proc.communicate()
print(out[-10:])
>>>
b'\x8c(\xed\xc7m1\xf0F4\xe6'
b'\x0eD\x97\xe9>\x10h{\xbd\xf0'
b'g\x93)\x14U\xa9\xdc\xdd\x04\xd2'
-
자식 프로세스 관리를 위해 procs 리스트에 저장하였다가 마지막 출력을 가져옴
-
출력은 암호화된 바이트 문자열
-
유닉스 파이프라인처럼 한 자식 프로세스의 출력을 다음 프로세스의 입력으로 계속 연결시켜 병렬 프로세스를 연쇄적으로 연결 가능
def run_hash(input_stdin):
return subprocess.Popen(
['openssl', 'dgst', '-whirlpool', '-binary'],
stdin=input_stdin,
stdout=subprocess.PIPE)
encrypt_procs = []
hash_procs = []
for _ in range(3):
data = os.urandom(100)
encrypt_proc = run_encrypt(data)
encrypt_procs.append(encrypt_proc)
hash_proc = run_hash(encrypt_proc.stdout)
hash_procs.append(hash_proc)
# 자식이 입력 스트림에 들어오는 데이터를 소비하고# communicate() 메서드가
# 불필요하게 자식으로부터 오는 입력을 훔쳐가지 못하게 만든다
# 또 다운스트림 프로세스가 죽으면# SIGPIPE를 업스트림 프로세스에 전달한다
encrypt_proc.stdout.close()
encrypt_proc.stdout = None
for proc in encrypt_procs:
proc.communicate()
assert proc.returncode == 0
for proc in hash_procs:
out, _ = proc.communicate()
print(out[-10:])
assert proc.returncode == 0
>>>
b'\xe2j\x98h\xfd\xec\xe7T\xd84'
b'\xf3.i\x01\xd74|\xf2\x94E'
b'5_n\xc3-\xe6j\xeb[i'
- 자식 프로세스가 끝나지 않는 경우, 블록될 수 있음
- timeout 파라미터 사용하여 끝날 수 있도록 하는 예제
proc = subprocess.Popen(['sleep', '10'])
try:
proc.communicate(timeout=0.1)
except subprocess.TimeoutExpired:
proc.terminate()
proc.wait()
print('종료 상태', proc.poll())
>>>
종료 상태 -15