본문 바로가기
Python/python

파이썬 subprocess 모듈을 이용해서 외부 프로그램 실행하기

by 노마드 산코디 2023. 10. 31.
728x90

안녕하세요. 오늘은 파이썬 subprocess 모듈에 대한 포스팅을 통해 파이썬에서 외부 프로세스를 실행하고 제어하는 방법을 알아보려고 합니다. subprocess 모듈은 파이썬에서 시스템 명령어를 실행하거나 다른 프로그램을 시작하는 데 유용한 도구입니다. 함께 subprocess 모듈의 사용법과 예제를 살펴보겠습니다.

 

 

 

 


1. subprocess 모듈이란?

subprocess 모듈은 파이썬에서 외부 프로세스를 생성하고 제어하는 데 사용되는 내장 모듈입니다. 이 모듈은 외부 명령어 실행, 다른 프로그램 실행, 표준 입력/출력/에러 스트림의 처리, 프로세스 상태 모니터링 및 통신, 환경 변수 설정 등 다양한 작업을 수행할 수 있도록 지원합니다.


함수의 주요 특징

  • 외부 명령어 실행
    subprocess
     모듈을 사용하여 운영 체제의 명령어나 실행 파일을 호출하고 그 결과를 파이썬 프로그램에서 사용할 수 있습니다.


  • 표준 입력/출력/에러 스트림 제어
    파이썬 스크립트와 외부 프로세스 간에 데이터를 주고받을 수 있으며, 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr) 스트림을 제어할 수 있습니다.


  • 프로세스 제어
    생성된 프로세스를 시작, 일시 중지, 재개, 종료 등을 관리할 수 있습니다.


  • 환경 변수 설정
    실행되는 외부 프로세스에 환경 변수를 설정할 수 있으며, 이를 통해 프로세스의 동작을 조정할 수 있습니다.


  • 프로세스 상태 모니터링
    실행 중인 프로세스의 상태를 모니터링하고 결과를 처리할 수 있습니다.


  • 효율적이고 안전한 방법
    subprocess
     모듈은 시스템 명령어를 실행할 때 표준 라이브러리의 일부로 구현되어 있으며, 안전하고 효율적인 방법으로 외부 프로세스와 상호 작용할 수 있습니다.



subprocess 모듈을 사용하면 파이썬 프로그램에서 운영 체제 수준의 작업을 수행하는 데 유용하며, 특히 시스템 관리, 자동화 및 데이터 처리와 같은 작업에 매우 유용합니다.









2. subprocess 모듈의 활용 예제



1. 외부 명령어 실행 및 결과 가져오기

import subprocess

# 'ls -l' 명령어 실행
result = subprocess.run(["ls", "-l"], stdout=subprocess.PIPE, text=True)

# 실행 결과 출력
print(result.stdout)


subprocess.run()을 사용하여 외부 명령어 실행, 표준 출력 캡처, 그리고 실행 결과를 변수에 저장합니다. 이를 통해 파이썬에서 외부 명령어 실행 및 결과 활용이 가능합니다.



2. 파이프로 외부 명령어 간 데이터 전달

import subprocess

# 'echo'로 텍스트 출력 후 'grep' 명령어로 필터링
text = "Hello, World!"
grep_process = subprocess.Popen(["echo", text], stdout=subprocess.PIPE, text=True)
result = subprocess.run(["grep", "World"], stdin=grep_process.stdout, stdout=subprocess.PIPE, text=True)

# 실행 결과 출력
print(result.stdout)


subprocess.Popen()으로 파이썬에서 echo 명령어를 실행하고, 그 결과를 grep 명령어로 필터링하여 특정 문자열을 검색합니다. 이렇게 파이프로 명령어를 연결하여 데이터를 전달하고 처리할 수 있습니다.



3. 비동기로 여러 명령어 실행

import subprocess

# 여러 명령어 비동기 실행
commands = ["ls", "pwd", "date"]
processes = [subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) for cmd in commands]

# 결과 출력
for process, cmd in zip(processes, commands):
    output, _ = process.communicate()
    print(f"Command: {cmd}")
    print(f"Output: {output}")


비동기적으로 여러 명령어를 동시에 실행하고, subprocess.run()으로 각 명령어의 실행 결과를 얻어옵니다. 이렇게 병렬로 명령어를 처리할 수 있습니다.




4. 외부 스크립트 실행 및 환경 변수 제어

import subprocess

# 파이썬 스크립트 실행, 환경 변수 설정
env = {"CUSTOM_ENV_VAR": "123"}
result = subprocess.run(["python", "myscript.py"], env=env, stdout=subprocess.PIPE, text=True)

# 실행 결과 출력
print(result.stdout)


subprocess.run()을 사용하여 외부 파이썬 스크립트를 실행하고, env 매개변수를 활용하여 스크립트 실행 환경 변수를 제어합니다. 이로써 외부 스크립트를 파이썬에서 유연하게 활용할 수 있습니다.



5. 에러 처리와 예외 발생

import subprocess

try:
    # 잘못된 명령어 실행
    result = subprocess.run(["nonexistentcommand"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
except subprocess.CalledProcessError as e:
    print("오류 발생:")
    print(e.stderr)


잘못된 명령어를 실행하면 subprocess.CalledProcessError 예외가 발생하며, 이를 try와 except를 사용하여 처리합니다. 이를 통해 오류 발생 시 예외를 잡고 적절한 조치를 취할 수 있습니다.




위의 예제들은 subprocess 모듈을 사용하여 외부 프로세스를 실행하고 그 결과를 처리하는 방법을 보여줍니다. 각각의 예제는 다양한 상황에서 유용하게 사용될 수 있습니다.


3. subprocess 모듈 사용시 주의사항



1. 보안
외부 명령어를 실행할 때, 사용자 입력을 직접 명령어에 포함시키면 보안 취약점이 될 수 있습니다. 사용자 입력을 사용하는 경우 적절한 검증과 이스케이핑을 수행하여 보안 문제를 방지해야 합니다.

2. 표준 입력
subprocess.Popen() 등으로 외부 명령어를 실행할 때, 표준 입력(stdin)을 조심히 처리해야 합니다. 무한대기 상태에 빠질 수 있으므로, 표준 입력이 필요 없는 경우에는 stdin=subprocess.PIPE 등을 사용하여 입력을 비활성화할 수 있습니다.

3. 표준 출력 및 에러 처리
외부 명령어의 표준 출력과 표준 에러는 별도의 스트림으로 처리됩니다. 따라서 이들 스트림을 적절히 처리해주어야 합니다. 일반적으로 표준 출력을 캡처하고 에러를 처리하는 것이 좋습니다.

4. Blocking
subprocess.run()과 subprocess.Popen()은 기본적으로 외부 명령어가 실행을 완료할 때까지 블록됩니다. 이를 비동기적으로 처리하려면 스레드나 asyncio와 함께 사용하거나, stdout=subprocess.PIPE 및 stderr=subprocess.PIPE를 사용하여 비동기적으로 결과를 캡처할 수 있습니다.

5. 환경 변수
외부 명령어를 실행할 때, 환경 변수를 제어하려면 env 매개변수를 사용하세요. 보안 및 성능상의 이유로 기본 환경 변수를 그대로 사용하는 것을 피하는 것이 좋습니다.

6. Cross-Platform 이슈
외부 명령어는 운영 체제에 따라 동작할 수 있는 방식이 다를 수 있습니다. 따라서 코드가 여러 플랫폼에서 동일하게 작동하는지 확인하고, 가능한 플랫폼 별로 대체 가능한 명령을 사용하는 것이 좋습니다.

7. 자원 누수
외부 명령어를 실행한 후에는 반드시 자원을 정리해야 합니다. subprocess.Popen을 사용한 경우에는 communicate() 또는 wait() 메서드를 사용하여 자원을 해제하는 것이 좋습니다.

8. 버퍼링
외부 명령어의 출력을 읽을 때, 버퍼링 문제가 발생할 수 있습니다. 이를 해결하기 위해 stdout=subprocess.PIPE 및 stderr=subprocess.PIPE를 사용하여 스트림을 캡처하고, 이 스트림을 비동기적으로 읽을 수 있도록 조치하는 것이 좋습니다.

 

 



 


4. subprocess 모듈의 자원 관리와 메모리 누수 방지



1. Popen 객체의 정리
subprocess.Popen 객체를 사용한 후에는 반드시 해당 객체를 정리해야 합니다. 이를 위해 communicate(), wait(), 또는 terminate() 및 kill() 메서드를 사용하여 프로세스를 종료하고 자원을 해제합니다.

process = subprocess.Popen(["command", "arguments"])
# 작업 수행
process.terminate()  # 또는 process.kill()
process.wait()




2. 표준 스트림 처리
외부 명령의 표준 출력 및 표준 에러는 별도의 스트림으로 처리됩니다. 이 스트림은 적절히 처리하지 않으면 자원 누수의 원인이 될 수 있습니다. 따라서 stdout=subprocess.PIPE, stderr=subprocess.PIPE를 사용하여 스트림을 캡처하고, communicate()를 통해 스트림을 읽어야 합니다.

process = subprocess.Popen(["command", "arguments"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()




3. Context Manager 사용
with문을 사용하여 Popen 객체를 관리하면 자원 누수를 방지할 수 있습니다. with문을 빠져나오면 자원이 자동으로 해제됩니다.

with subprocess.Popen(["command", "arguments"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as process:
    stdout, stderr = process.communicate()




4. 예외 처리
subprocess.Popen 객체를 사용할 때 예외 처리를 활용하여 예외 상황에서도 자원을 제대로 정리하도록 합니다.

try:
    process = subprocess.Popen(["command", "arguments"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
except Exception as e:
    print(f"An error occurred: {e}")
finally:
    process.terminate()  # 또는 process.kill()
    process.wait()




5. Timeout 설정
timeout 매개변수를 사용하여 외부 명령어의 실행 시간을 제한하는 것이 좋습니다. 이를 통해 실행이 끝나지 않는 상황을 방지할 수 있습니다.

try:
    process = subprocess.Popen(["command", "arguments"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30)
    stdout, stderr = process.communicate()
except subprocess.TimeoutExpired:
    print("The command timed out.")
    process.terminate()
    process.wait()




자원 관리와 메모리 누수 방지를 위해 Popen 객체를 신중하게 다루고, 외부 명령어의 실행이 완료되면 적절하게 정리해야 합니다.

 

 




최종 정리

오늘은 파이썬 subprocess 모듈에 대한 내용을 주제로 정리해 보았습니다. subprocess 모듈은 외부 프로세스를 생성하고 제어하는데 매우 유용한 도구입니다. 이를 통해 파이썬 프로그램에서 다른 프로그램을 실행하고 그 결과를 가져올 수 있으며, 다양한 시스템 관리 및 자동화 작업에 활용할 수 있습니다.

감사합니다.

 

 

 

728x90
반응형