✅ 동기적 vs 비동기적

✅ 동기적(synchronous):

"기다렸다가 다음 일을 한다."

  • A 작업이 끝날 때까지 기다린 후 B 작업을 시작함

  • 코드 예 (파이썬):

	import subprocess
	subprocess.run(['sleep', '5'])  # A, 5초 동안 기다림
	print("끝났습니다!")  # B, 이건 5초 뒤에 출력됨

✅ 비동기적(asynchronous):

"기다리지 않고 다음 일을 동시에 한다."

  • A 작업을 백그라운드에서 실행하면서, 동시에 B 작업을 진행

  • 코드 예:

	import subprocess
	p = subprocess.Popen(['sleep', '5'])  # 5초 자는 명령 실행
	print("끝났습니다!")  # 이건 바로 출력됨!

✅ 백그라운드 실행이란?

"프로그램을 실행하긴 하는데, 뒤에서 돌리고 나는 다른 일 함"

예:

  • 우리가 직접 브라우저는 안 띄우고, 프로그램이 대신 인터넷 검색해주는 것
  • 터미널에서 python my_script.py & 이렇게 쓰면 백그라운드 실행

파이썬에서 예:

import subprocess
p = subprocess.Popen(['ping', 'google.com']) # ping: 네트워크 연결 확인 명령어
# 브라우저처럼 띄우지 않고, 뒤에서 실행만 함

✅ 리눅스 파이프(|) 연결이란?

여러 명령을 파이프로 연결해서, 앞의 출력을 뒤에 전달하는 것

예 (터미널에서):

ls -l | grep py
  • ls -l = 모든 파일 목록 출력
  • grep py = 그중 .py만 걸러냄
  • | = 파이프, 즉 "앞 출력 → 뒤 입력"

파이썬으로 하면:

import subprocess

p1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', 'py'], stdin=p1.stdout, stdout=subprocess.PIPE)

output = p2.communicate()[0]
print(output.decode())

🎯 다시 요약

개념쉬운 설명현실 비유
동기끝날 때까지 기다림🍜 라면 끓이고 → 먹음
비동기동시에 처리🍜 라면 끓이면서 → 드라마
백그라운드 실행눈에 안 보이게 뒤에서 돌림🚶‍♂️ 타이머 켜놓고 다른 일 함
파이프 연결앞 명령 출력 → 뒤 명령 입력🍽 채소 자르고 → 국에 넣음

subprocess.run()subprocess.Popen()

✅ 공통점

  • 둘 다 subprocess 모듈에 포함되어 있음
  • 외부 명령어(ex: ls, ping, python script.py) 실행 가능

🔀 차이 요약표

항목subprocess.run()subprocess.Popen()
파이썬 버전Python 3.5+Python 2.x ~ 최신
실행 방식동기적 (완료까지 기다림)비동기적 (실시간 실행)
사용 난이도간단함 (고수준 API)복잡하지만 유연함 (저수준 API)
결과 처리CompletedProcess 객체 반환표준 스트림 직접 관리 필요
백그라운드 실행❌ 어려움✅ 가능
리눅스 파이프 연결기본적으로 안 됨자유롭게 가능 (stdin, stdout 조합)

🔹 subprocess.run() 예제

import subprocess

# ls -l 실행
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)

print(result.stdout)
print("리턴코드:", result.returncode)

run()프로세스를 기다렸다가, 끝난 뒤 결과를 CompletedProcess 객체로 돌려줘요.
> CompletedProcess 객체의 자세한 사용법 <


🔹 subprocess.Popen() 예제

import subprocess

# 실시간 출력 받기
process = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE, text=True)

for line in process.stdout:
    print(line.strip())

process.wait()

Popen()명령 실행 후 바로 제어권을 반환하므로, 출력도 실시간으로 받을 수 있어요.


✅ 언제 어떤 걸 써야 할까?

상황추천 함수
명령 한 번 실행하고 결과만 필요subprocess.run()
실시간 출력 확인이 필요subprocess.Popen()
입력/출력 파이프 연결Popen() (예: stdout=PIPE)
명령이 오래 걸릴 수 있고 병렬로 처리하고 싶을 때Popen()
Python 3.5 이상이고 단순 작업이면run() 사용 권장

🔁 추가 팁: Popen에서 communicate()

out, err = process.communicate()
  • 표준 출력과 에러를 프로세스가 종료된 후에 한 번에 읽음

communicate()

subprocess.Popen().communicate() 함수는 외부 프로세스와 데이터를 주고받을 때 사용하는 중요한 함수인데요, **전달할 수 있는 인자(arguments)**는 몇 개 안 되지만 아주 유용합니다. 아래에 인자별 설명과 예제를 정리해드릴게요.


communicate() 함수 기본 형태

stdout_data, stderr_data = process.communicate(input=None, timeout=None)

input

📌 용도:

  • 표준 입력(stdin) 으로 데이터를 보내고 싶을 때 사용

📋 타입:

  • bytes (기본)
  • 또는 str (단, text=True 또는 universal_newlines=True일 때만)

🔹 예제:

import subprocess

p = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, _ = p.communicate(input=b'hello\n') # 문자열을 bytes형으로 변환
print(out.decode())  # 출력: hello

timeout

📌 용도:

  • 제한된 시간 안에 명령이 끝나지 않으면 강제로 TimeoutExpired 예외 발생

📋 타입:

  • 숫자 (초 단위, float 또는 int)

🔹 예제:

import subprocess

try:
    p = subprocess.Popen(['sleep', '5'], stdout=subprocess.PIPE)
    p.communicate(timeout=2)
except subprocess.TimeoutExpired:
    print("타임아웃 발생!")  # 2초 뒤 출력

✅ 3. (주의) input을 쓰려면 stdin=PIPE가 필요함

# 잘못된 사용 – stdin 설정 안 하면 input 전달 불가
p = subprocess.Popen(['cat'])  
p.communicate(input=b'hello')  # 오류 발생!

➤ 수정:

p = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
p.communicate(input=b'hello')  # OK

🧠 요약

인자설명주의사항
inputstdin으로 보낼 데이터stdin=subprocess.PIPE 필요
timeout시간 초과 제한 (초 단위)초과 시 TimeoutExpired 발생

✅ 반환값

stdout_data, stderr_data = process.communicate(...)
  • stdout_data: 표준 출력 결과 (stdout=PIPE일 때만)
  • stderr_data: 표준 에러 결과 (stderr=PIPE일 때만)

profile
개발자

0개의 댓글