29.Python subprocess로 외부 명령어 실행하기: VSCode 실전 활용법
저도 처음에는 회사에서 매일 반복하던 번거로운 서버 배포 작업을 자동화해 보려고, 파이썬 스크립트 안에 깃(git) 명령어를 넣어 실행하는 코드를 짰던 것이 시작이었습니다. 분명 내 터미널에 직접 입력할 때는 잘만 되던 명령어가, 파이썬 코드로 실행하니 자꾸 FileNotFoundError만 뱉어내서 도대체 뭐가 문제인지 몇 시간이나 소스 코드 이 줄 저 줄을 뜯어고치며 밤새 삽질을 했습니다. 알고 보니 코드가 아니라 VS Code가 명령 프로그램의 위치를 찾지 못하는 'PATH 환경변수' 문제였죠. 실행 경로를 명시해 주자마자 스크립트가 배포 작업을 알아서 척척 단 5초 만에 끝내는 걸 보고, 저는 이 파이썬 자동화의 강력함에 완전히 매료되었습니다. 이번 글에서는 그때의 시행착오를 바탕으로 subprocess를 활용해 외부 명령어를 안전하게 제어하는 방법을 정리해 보겠습니다.
Python 코드 안에서 터미널 명령어를 직접 실행하고 싶었던 적이 있으신가요? 예를 들어 git, ffmpeg, curl 같은 외부 프로그램을 Python 스크립트 안에서 자동으로 호출하고 그 결과를 받아와야 하는 경우가 생각보다 자주 발생합니다. 이럴 때 필요한 것이 바로 subprocess 모듈이며, 이를 활용하면 Python이 마치 터미널을 대신 조작하는 것처럼 외부 프로그램을 자유자재로 실행할 수 있습니다. 이번 글에서는 VSCode 환경에서 Python subprocess를 활용해 외부 명령어를 실행하고 결과를 처리하는 방법을 실전 예제와 함께 정리해보겠습니다.
subprocess란 무엇인가
Python에서 외부 프로세스를 실행하는 표준 모듈
subprocess는 Python 표준 라이브러리에 내장된 모듈로, Python 코드 안에서 운영체제의 명령어나 다른 프로그램을 새로운 프로세스로 실행할 수 있게 해줍니다. 쉽게 말해 여러분이 평소 터미널에 직접 타이핑하던 명령어를, Python 코드가 대신 입력해주고 그 결과까지 받아와주는 것이라고 이해하면 됩니다.
비유하자면 subprocess는 마치 직접 카페에 가서 커피를 주문하는 대신, 직원에게 주문서를 건네주고 완성된 커피를 받아오는 심부름꾼과 같습니다. Python이라는 본체는 자리에 앉아 있고, subprocess가 대신 밖에 나가서 명령어라는 주문을 처리한 뒤 결과물을 가져다주는 셈입니다.
subprocess가 필요한 대표적인 상황
- Git 명령어를 자동화 스크립트 안에서 실행할 때
- ffmpeg 같은 외부 프로그램으로 영상, 이미지를 변환할 때
- 시스템 명령어(디렉토리 목록 조회, 파일 이동 등)를 자동화할 때
- 다른 언어로 작성된 스크립트를 Python에서 호출할 때
- 여러 프로그램을 연결하는 파이프라인을 구축할 때
VSCode에서 subprocess 실습 환경 준비하기
기본 실행 확인하기
subprocess는 별도의 설치 과정 없이 Python 표준 라이브러리에 포함되어 있어서 바로 import해서 사용할 수 있습니다. VSCode에서 새 Python 파일을 만들고 다음 코드를 실행해보겠습니다.
import subprocess
result = subprocess.run(['python', '--version'], capture_output=True, text=True)
print(result.stdout)
실행 경로 문제 주의하기
저도 처음에 PATH에서 막혔는데, 분명히 터미널에서는 잘 되는 명령어를 subprocess로 실행하면 FileNotFoundError가 발생해서 당황했던 적이 있습니다. 알고 보니 VSCode가 사용하는 파이썬 환경과 실제 명령어 프로그램이 설치된 경로가 시스템 PATH에 제대로 등록되어 있지 않았던 것이 원인이었고, 명령어의 전체 경로를 직접 지정하거나 shell=True 옵션을 추가해주고 나서야 해결할 수 있었습니다.
import subprocess
result = subprocess.run('python --version', shell=True, capture_output=True, text=True)
print(result.stdout)
다만 shell=True 옵션은 보안상 주의가 필요하므로, 가능하다면 명령어와 인자를 리스트 형태로 명확히 분리해서 작성하는 방식을 우선적으로 고려하는 것이 좋습니다.
subprocess 기본 사용법 실습
run() 함수로 명령어 실행하고 결과 받기
subprocess.run()은 명령어를 실행하고 그 결과를 기다렸다가 반환해주는 가장 기본적이고 널리 쓰이는 방법입니다.
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print("표준 출력:", result.stdout)
print("에러 출력:", result.stderr)
print("종료 코드:", result.returncode)
returncode가 0이면 정상적으로 실행이 완료된 것이고, 0이 아니라면 어떤 형태로든 오류가 발생했다는 신호이므로 이 값을 확인하는 습관을 들이는 것이 중요합니다.
명령어 실행 결과에 따라 분기 처리하기
실무에서는 명령어 실행 성공 여부에 따라 다음 로직을 다르게 처리해야 하는 경우가 많습니다.
import subprocess
result = subprocess.run(['git', 'status'], capture_output=True, text=True)
if result.returncode == 0:
print("Git 상태 확인 성공:")
print(result.stdout)
else:
print("오류 발생:")
print(result.stderr)
표준 입력값 전달하기
명령어 실행 중에 입력값을 전달해야 하는 경우에는 input 파라미터를 활용할 수 있습니다.
import subprocess
result = subprocess.run(
['python3', '-c', 'name = input(); print(f"안녕하세요, {name}님")'],
input='홍길동',
capture_output=True,
text=True
)
print(result.stdout)
실전 활용 팁
실행 시간이 긴 명령어 다루기
시간이 오래 걸리는 명령어를 실행할 때는 무한정 기다리지 않도록 timeout 옵션을 설정하는 것이 안전합니다. 마치 전화 상담을 걸었을 때 응답이 없으면 일정 시간 뒤 자동으로 끊어버리는 것처럼, 예상치 못한 응답 지연으로 프로그램 전체가 멈춰버리는 상황을 방지할 수 있습니다.
import subprocess
try:
result = subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print("명령어 실행 시간이 초과되었습니다.")
예외 처리로 안정성 높이기
명령어 실행 과정에서 예상치 못한 오류가 발생할 수 있으므로, try-except 구문으로 감싸주는 것이 안정적인 코드를 작성하는 기본입니다.
import subprocess
try:
result = subprocess.run(['존재하지않는명령어'], capture_output=True, text=True, check=True)
except FileNotFoundError:
print("명령어를 찾을 수 없습니다.")
except subprocess.CalledProcessError as e:
print(f"명령어 실행 중 오류 발생: {e}")
check=True 옵션을 추가하면 명령어가 실패했을 때 자동으로 예외를 발생시켜주기 때문에, 오류 처리 로직을 훨씬 명확하게 작성할 수 있습니다.
마무리
지금까지 Python subprocess 모듈을 활용해 외부 명령어를 실행하고 결과를 처리하는 방법을 VSCode 환경에서 실습해봤습니다. 처음에는 경로 문제나 예외 처리 때문에 헤맬 수 있지만, 기본 흐름을 익히고 나면 다양한 자동화 스크립트에 두루 활용할 수 있는 강력한 도구가 됩니다.
핵심 내용을 정리하면 다음과 같습니다.
- subprocess는 Python 코드 안에서 외부 명령어나 프로그램을 실행할 수 있게 해주는 표준 모듈입니다
subprocess.run()으로 명령어를 실행하고capture_output,text옵션으로 결과를 손쉽게 받아올 수 있습니다- 명령어와 인자는 되도록 리스트 형태로 분리해서 작성하는 것이 안전합니다
timeout과try-except구문을 활용하면 실행 중 발생할 수 있는 예외 상황에 안정적으로 대응할 수 있습니다returncode와check=True옵션을 통해 명령어 실행 성공 여부를 명확히 확인하는 습관이 중요합니다
다음 글에서는 subprocess를 활용해 여러 프로그램을 파이프로 연결하거나, 실시간으로 출력 결과를 스트리밍하는 방법에 대해 더 자세히 다뤄보도록 하겠습니다.
댓글
댓글 쓰기