파이썬에서 외부 명령 호출


4882

파이썬 스크립트에서 외부 명령 (유닉스 쉘이나 Windows 명령 프롬프트에서 입력 한 것처럼)을 어떻게 호출합니까?

답변:


4692

표준 라이브러리에서 서브 프로세스 모듈을 보십시오 .

import subprocess
subprocess.run(["ls", "-l"])

의 장점 subprocess대는 system가 (당신이 얻을 수있는 더 유연하다는 것이다 stdout, stderr, "진짜"상태 코드, 더 나은 오류 처리, 등 ...).

공식 문서는 권장 subprocess대체를 통해 모듈 os.system():

subprocess모듈은 새로운 프로세스를 생성하고 결과를 검색 할 수있는보다 강력한 기능을 제공합니다. 이 기능을 사용하는 것보다 해당 모듈을 사용하는 것이 좋습니다 os.system().

문서의 이전 프로세스를 서브 프로세스 모듈로 대체 섹션에 subprocess유용한 레시피가있을 수 있습니다.

3.5 이전의 Python 버전의 경우 call다음을 사용하십시오 .

import subprocess
subprocess.call(["ls", "-l"])

변수 대체를 사용하는 방법이 있습니까? IE는 echo $PATH을 사용하여 시도했지만 대체 대신 call(["echo", "$PATH"])리터럴 문자열을 에코했습니다 $PATH. PATH 환경 변수를 얻을 수 있다는 것을 알고 있지만 bash에서 명령을 실행 한 것처럼 명령을 정확하게 수행하는 쉬운 방법이 있는지 궁금합니다.
Kevin Wheeler

@KevinWheeler 당신은 shell=True그것이 작동 하기 위해 사용해야 합니다.
SethMMorton

38
@KevinWheeler shell=True이 목적으로 파이썬은 os.path.expandvars 와 함께 사용해서는 안됩니다 . 귀하의 경우 다음과 같이 작성할 수 있습니다 os.path.expandvars("$PATH").. @SethMMorton 귀하의 의견을 재고하십시오-> shell = True
Murmel

통화가 차단 되나요? 즉, for루프 에서 여러 명령을 실행하려면 파이썬 스크립트를 차단하지 않고 어떻게해야합니까? 명령의 출력에 신경 쓰지 않고 단지 많은 명령을 실행하고 싶습니다.
Charlie Parker

4
매개 변수를 사용하여 명령에서 목록작성 하려면 subprocesswhen 과 함께 사용할 수있는 목록을 작성 하십시오. docs.python.org/2/library/shlex.html#shlex.splitshell=Falseshlex.split
Daniel F

2982

다음은 외부 프로그램을 호출하는 방법과 각각의 장단점을 요약 한 것입니다.

  1. os.system("some_command with args")명령과 인수를 시스템 쉘에 전달합니다. 실제로이 방법으로 여러 명령을 한 번에 실행하고 파이프 및 입 / 출력 리디렉션을 설정할 수 있기 때문에 좋습니다. 예를 들면 다음과 같습니다.

    os.system("some_command < input_file | another_command > output_file")  

그러나 이것은 편리하지만 공백과 같은 쉘 문자의 이스케이프 처리를 수동으로 처리해야합니다. 반면에, 이것은 실제로 외부 프로그램이 아닌 단순히 쉘 명령 인 명령을 실행할 수있게합니다. 설명서를 참조하십시오 .

  1. stream = os.popen("some_command with args")os.system해당 프로세스의 표준 입 / 출력에 액세스하는 데 사용할 수있는 파일과 유사한 객체를 제공한다는 점을 제외하고 는 동일한 작업을 수행합니다 . 모두 다른 방식으로 i / o를 처리하는 3 가지 다른 종류의 popen이 있습니다. 모든 것을 문자열로 전달하면 명령이 셸로 전달됩니다. 당신이 그들을 목록으로 전달하면 아무것도 탈출에 대해 걱정할 필요가 없습니다. 설명서를 참조하십시오 .

  2. 모듈 의 Popen클래스 subprocess. 이것은 대체 용으로 고안 os.popen되었지만 너무 포괄적이기 때문에 약간 더 복잡하다는 단점이 있습니다. 예를 들어 다음과 같이 말할 수 있습니다.

    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()

    대신에:

    print os.popen("echo Hello World").read()

    그러나 4 가지 다른 popen 함수 대신 하나의 통합 클래스에서 모든 옵션을 사용하는 것이 좋습니다. 설명서를 참조하십시오 .

  3. 모듈 의 call기능 subprocess. 이것은 기본적으로 Popen클래스와 같으며 동일한 인수를 모두 사용하지만 명령이 완료 될 때까지 기다렸다가 리턴 코드를 제공합니다. 예를 들면 다음과 같습니다.

    return_code = subprocess.call("echo Hello World", shell=True)  

    설명서를 참조하십시오 .

  4. Python 3.5 이상을 사용하는 subprocess.run경우 위와 비슷하지만 더 유연하고 CompletedProcess명령 실행이 완료되면 객체를 반환하는 새로운 함수를 사용할 수 있습니다 .

  5. os 모듈에는 C 프로그램에서 가질 수있는 모든 fork / exec / spawn 함수가 있지만 직접 사용하지 않는 것이 좋습니다.

subprocess아마도 당신이 사용 하는 모듈 일 것입니다.

마지막으로 쉘이 문자열로 실행하도록 최종 명령을 전달하는 모든 메소드에 대해 이스케이프 처리해야합니다. 전달하는 문자열의 일부를 완전히 신뢰할 수없는 경우 보안에 심각한 영향을 미칩니다 . 예를 들어, 사용자가 문자열의 일부 또는 일부를 입력하는 경우. 확실하지 않은 경우 상수와 함께이 방법 만 사용하십시오. 의미에 대한 힌트를 제공하려면 다음 코드를 고려하십시오.

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

사용자가 전체 파일 시스템을 지울 수있는 "엄마가 나를 사랑하지 않는 && rm -rf /"라는 것을 입력했다고 상상해보십시오.


22
좋은 답변 / 설명. 이 기사에서 설명한대로 파이썬의 좌우명을 정당화하는이 답변은 어떻습니까? fastcompany.com/3026446/… " 전통적으로 , Perl과 Python에는 다른 철학이 있습니다. Perl의 가장 잘 알려진 모토는"한 가지 이상의 방법이 있습니다. " 다른 방법! Perl에서는 back-tick 또는를 사용하여 명령을 실행하는 두 가지 방법 만 알고 open있습니다.
Jean

12
Python 3.5 이상을 사용하는 경우을 사용하십시오 subprocess.run(). docs.python.org/3.5/library/subprocess.html#subprocess.run
피닉스

4
일반적으로 알아야 할 것은 자식 프로세스의 STDOUT 및 STDERR로 수행되는 작업입니다. 무시할 경우 일부 (일반적인) 조건 하에서 자식 프로세스는 STDOUT에 쓰기 위해 시스템 호출을 발행합니다 (STDERR?). 그것은 OS에 의해 프로세스에 제공된 출력 버퍼를 초과 할 것이고, OS는 일부 프로세스가 그 버퍼에서 읽을 때까지 그것을 차단하게 할 것입니다. 그래서, 현재 권장되는 방법으로, subprocess.run(..)정확히 무엇을 "이것은 기본적으로 표준 출력 또는 표준 오류를 캡처하지 않습니다." 암시? 어떤 약 subprocess.check_output(..)및 STDERR?
Evgeni Sergeev 2016 년

2
@Pitto는 그렇습니다. 그러나 그것은 예제에서 실행되는 것이 아닙니다. 에 echo전달 된 문자열 앞에 Popen? 따라서 전체 명령은입니다 echo my mama didnt love me && rm -rf /.
Chris Arndt

6
이것은 아마도 잘못된 길입니다. 대부분의 사람들 subprocess.run()은 그보다 오래된 형제 자매 만 필요합니다 subprocess.check_call(). 이것으로 충분하지 않은 경우를 참조하십시오 subprocess.Popen(). os.popen()전혀 언급하지 말거나 "자신의 포크 / exec / spawn 코드를 해킹"한 후에도 언급되지 않아야합니다.
트리플 리

357

일반적인 구현 :

import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

stdout파이프 의 데이터로 원하는 것을 자유롭게 할 수 있습니다 . 실제로 이러한 매개 변수 ( stdout=stderr=) 를 생략하면 다음 과 같이 작동합니다 os.system().


44
.readlines()모든 행을 한 번에 읽습니다. 즉, 하위 프로세스가 종료 될 때까지 (파이프의 끝을 닫음) 차단합니다. 실시간으로 읽으려면 (버퍼링 문제가없는 경우) 다음을 수행 할 수 있습니다.for line in iter(p.stdout.readline, ''): print line,
jfs

1
"버퍼링 문제가없는 경우"의 의미에 대해 자세히 설명해 주시겠습니까? 프로세스가 확실하게 차단되면 하위 프로세스 호출도 차단됩니다. 원래 예제에서도 마찬가지입니다. 버퍼링과 관련하여 다른 일이 발생할 수 있습니까?
EmmEff

15
자식 프로세스 라인 버퍼링 때문에 대신 비 - 대화 형 모드에서 블록 버퍼링을 사용할 수 없다 p.stdout.readline()(참고 : s끝) 아이가 버퍼를 채울 때까지 모든 데이터를 볼 수 없다. 자식이 많은 데이터를 생성하지 않으면 출력이 실시간이 아닙니다. Q 의 두 번째 이유를보십시오 : 왜 파이프 (popen ())를 사용하지 않습니까? . 이 답변 에는 몇 가지 해결 방법이 있습니다 (pexpect, pty, stdbuf)
jfs

4
버퍼링 문제는 실시간으로 출력을 원하고 모든 데이터가 수신 될 때까지 아무것도 인쇄하지 않는 코드에는 적용되지 않는 경우에만 중요합니다.
jfs

3
이 답변은 당시에는 좋았지 만 더 이상 Popen간단한 작업을 권장하지 않습니다 . 이것도 불필요하게 지정합니다 shell=True. subprocess.run()답 중 하나를 시도하십시오 .
tripleee

230

하위 프로세스를 호출 프로세스에서 분리하는 방법에 대한 힌트 (백그라운드에서 하위 프로세스 시작).

CGI 스크립트에서 긴 작업을 시작한다고 가정합니다. 즉, 하위 프로세스는 CGI 스크립트 실행 프로세스보다 오래 지속되어야합니다.

서브 프로세스 모듈 문서의 전형적인 예는 다음과 같습니다.

import subprocess
import sys

# Some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess

# Some more code here

longtask.py가 끝날 때까지 'call subprocess'줄을 기다리지 않기를 원합니다. 그러나 예제에서 '여기에 더 많은 코드가 있습니다'행 이후에 어떤 일이 발생하는지 명확하지 않습니다.

내 목표 플랫폼은 FreeBSD 였지만 개발은 Windows에 있었으므로 Windows에서 먼저 문제에 직면했습니다.

Windows (Windows XP)에서는 longtask.py가 작업을 완료 할 때까지 상위 프로세스가 완료되지 않습니다. CGI 스크립트에서 원하는 것이 아닙니다. 이 문제는 파이썬에만 국한된 것이 아닙니다. PHP 커뮤니티에서 문제는 동일합니다.

해결책은 DETACHED_PROCESS Process Creation Flag 를 Windows API의 기본 CreateProcess 함수에 전달하는 것입니다. pywin32를 설치 한 경우 win32process 모듈에서 플래그를 가져올 수 있습니다. 그렇지 않으면 직접 정의해야합니다.

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/ * UPD 2015.10.27 @eryksun 아래 주석에서 의미 적으로 올바른 플래그는 CREATE_NEW_CONSOLE (0x00000010) * /입니다.

FreeBSD에는 또 다른 문제가 있습니다. 부모 프로세스가 완료되면 자식 프로세스도 완료됩니다. 그리고 그것은 CGI 스크립트에서 원하는 것이 아닙니다. 일부 실험에서는 sys.stdout을 공유하는 데 문제가있는 것으로 나타났습니다. 작업 솔루션은 다음과 같습니다.

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

다른 플랫폼에서 코드를 확인하지 않았으며 FreeBSD에서 동작의 이유를 모릅니다. 누구나 알고 있다면 아이디어를 공유하십시오. 파이썬에서 백그라운드 프로세스를 시작하는 인터넷 검색은 아직 밝혀지지 않았습니다.


pydev + eclipse에서 py2exe 앱을 개발할 때 가능한 "분할"을 발견했습니다. 이클립스의 출력 창이 종료되지 않았기 때문에 메인 스크립트가 분리되지 않았다고 말할 수있었습니다. 스크립트가 완료되어 실행 되더라도 여전히 리턴을 기다리고 있습니다. 그러나 py2exe 실행 파일로 컴파일하려고 할 때 예상되는 동작이 발생합니다 (프로세스가 분리 된 상태로 실행 한 다음 종료됩니다). 확실하지 않지만 실행 파일 이름이 더 이상 프로세스 목록에 없습니다. 이것은 모든 접근 방식 (os.system ( "start *"), os.P_DETACH를 사용하는 os.spawnl, 서브 프로세스 등)에서 작동합니다.
maranas

1
CREATE_NEW_PROCESS_GROUP 플래그가 필요할 수도 있습니다. 참조 는 popen은 바로 아이가 종료 된 경우에도 자식 프로세스를 기다리는
JFS

5
"[o] n windows (win xp), longtask.py가 작업을 완료 할 때까지 상위 프로세스가 완료되지 않습니다." 부모는 정상적으로 종료되지만 콘솔 창 (conhost.exe 인스턴스)은 마지막으로 연결된 프로세스가 종료 될 때만 닫히고 자식은 부모의 콘솔을 상속했을 수 있습니다. 설정 DETACHED_PROCESS에서 creationflags상속 또는 콘솔을 만드는에서 아이를 방지하여 피합니다이. 대신 새 콘솔을 원하면 CREATE_NEW_CONSOLE(0x00000010)을 사용하십시오.
Eryk Sun

1
분리 된 프로세스로 실행하는 것이 잘못되었다는 의미는 아닙니다. 즉, 파일, 파이프에 대한 표준 핸들을 설정하거나 os.devnull일부 콘솔 프로그램이 오류와 함께 종료되기 때문에 필요할 수 있습니다 . 자식 프로세스가 부모 프로세스와 동시에 사용자와 상호 작용하도록하려면 새 콘솔을 만듭니다. 단일 창에서 두 가지를 모두 시도하는 것은 혼란 스러울 것입니다.
Eryk Sun

1
백그라운드에서 프로세스를 실행하는 OS에 구애받지 않는 방법이 있습니까?
Charlie Parker

151
import os
os.system("your command")

명령이 정리되지 않았으므로 위험합니다. 'os'및 'sys'모듈에 대한 관련 문서는 Google에 맡기십시오. 비슷한 기능을 수행하는 많은 함수 (exec * 및 spawn *)가 있습니다.


6
거의 10 년 전에 무슨 의미인지 알 수 없지만 (날짜를 확인하십시오!) 추측해야한다면 검증이 수행되지 않았을 것입니다.
nimish

1
이것은 이제 subprocess좀 더 다재다능하고 휴대 가능한 솔루션으로 지적해야 합니다. 물론 외부 명령을 실행하는 것은 본질적으로 이식이 불가능하며 (지원해야하는 모든 아키텍처에서 명령을 사용할 수 있는지 확인해야 함) 외부 명령으로 사용자 입력을 전달하는 것은 본질적으로 안전하지 않습니다.
tripleee

1
이 사람의 타임 스탬프에 주목하십시오. "정확한"답변은 투표의 40 배이며 답변 # 1입니다.
nimish December

NodeJS를 실행하는 데 도움이 된 하나의 솔루션입니다.
Nikolay Shindarov

147

os.system 대신 subprocess 모듈을 사용하는 것이 좋습니다. 쉘 이스케이프 처리가 훨씬 안전하기 때문입니다.

subprocess.call(['ping', 'localhost'])

매개 변수를 사용하여 명령에서 목록작성 하려면 subprocesswhen 과 함께 사용할 수있는 목록을 작성 하십시오. docs.python.org/2/library/shlex.html#shlex.split ( 그것은 문서에 따라 권장되는 방법 docs.python.org/2/library/subprocess.html#popen-constructor )shell=Falseshlex.split
다니엘 F

6
" 셸이 이스케이프 처리하므로 훨씬 안전 합니다." 서브 프로세스는 쉘 이스케이프를 수행하지 않으며 서브 프로세스는 쉘을 통해 명령을 전달하지 않으므로 쉘 이스케이프가 필요하지 않습니다.
Lie Ryan

143
import os
cmd = 'ls -al'
os.system(cmd)

명령 결과를 반환하려면을 사용할 수 있습니다 os.popen. 그러나 이것은 하위 프로세스 모듈 을 선호하여 버전 2.6 이후 더 이상 사용되지 않으며 다른 답변도 잘 다루었습니다.



os.system 호출로 결과를 저장할 수도 있습니다. 예를 들어 os.system ( 'ls -l> test2.txt')와 같은 UNIX 쉘 자체처럼 작동하기 때문입니다.
Stefan Gruenwald

97

파이썬으로 외부 명령을 호출 할 수있는 다양한 라이브러리가 있습니다. 각 라이브러리에 대해 설명하고 외부 명령을 호출하는 예를 보여주었습니다. 예제로 사용한 명령은 ls -l(모든 파일 나열)입니다. 라이브러리에 대해 더 자세히 알고 싶다면 각 라이브러리에 대한 문서를 나열하고 링크했습니다.

출처 :

다음은 모든 라이브러리입니다.

바라건대 이것은 사용할 라이브러리를 결정하는 데 도움이 될 것입니다. :)

하위 프로세스

서브 프로세스를 통해 외부 명령을 호출하고 해당 입력 / 출력 / 오류 파이프 (stdin, stdout 및 stderr)에 연결할 수 있습니다. 서브 프로세스는 명령 실행을위한 기본 선택이지만 때로는 다른 모듈이 더 좋습니다.

subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command

os

os는 "운영 체제 종속 기능"에 사용됩니다. 또한 외부 명령을 호출하는 데 사용할 수 있습니다 os.systemos.popen(참고 :이 또한있는 subprocess.popen). os는 항상 셸을 실행하며 사용할 필요가 없거나 사용 방법을 모르는 사람들을위한 간단한 대안입니다 subprocess.run.

os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output

sh는 마치 마치 마치 프로그램 인 것처럼 프로그램을 호출 할 수있는 하위 프로세스 인터페이스입니다. 명령을 여러 번 실행하려는 경우에 유용합니다.

sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function

plumbum은 "스크립트와 같은"Python 프로그램을위한 라이브러리입니다. 에서와 같은 기능과 같은 프로그램을 호출 할 수 있습니다 sh. Plumbum은 셸없이 파이프 라인을 실행하려는 경우에 유용합니다.

ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command

기대하다

pexpect를 사용하면 자식 응용 프로그램을 생성하고 제어하고 출력에서 ​​패턴을 찾을 수 있습니다. 이것은 유닉스에서 tty를 기대하는 명령에 대한 하위 프로세스에 대한 더 나은 대안입니다.

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')

구조

fabric은 Python 2.5 및 2.7 라이브러리입니다. 로컬 및 원격 쉘 명령을 실행할 수 있습니다. 패브릭은 SSH (Secure Shell)에서 명령을 실행하는 간단한 대안입니다.

fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output

사절

특사는 "인간 하위 프로세스"로 알려져 있습니다. subprocess모듈 주위의 편의 래퍼로 사용됩니다 .

r = envoy.run("ls -l") # Run command
r.std_out # get output

명령

commands에 대한 래퍼 함수가 포함되어 os.popen있지만 subprocess더 나은 대안 이므로 Python 3에서 제거되었습니다 .

편집은 JF Sebastian의 의견을 기반으로합니다.


74

나는 항상 fabric다음과 같은 것들을 사용 합니다 :

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

그러나 이것은 좋은 도구 인 것 같습니다 : sh(Python subprocess interface) .

예를보십시오 :

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)

73

"pexpect"Python 라이브러리도 확인하십시오.

ssh, ftp, telnet 등의 외부 프로그램 / 명령을 대화식으로 제어 할 수 있습니다. 다음과 같이 입력하면됩니다.

child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password')

70

표준 라이브러리

하위 프로세스 모듈 (Python 3)을 사용하십시오 .

import subprocess
subprocess.run(['ls', '-l'])

권장되는 표준 방법입니다. 그러나보다 복잡한 작업 (파이프, 출력, 입력 등)은 구성하고 작성하는 데 지루할 수 있습니다.

Python 버전에 대한 참고 사항 : 여전히 Python 2를 사용하는 경우 subprocess.call도 비슷한 방식으로 작동합니다.

ProTip : shlex.split 을 사용 run하면 call, 및 기타 subprocess함수에 대한 명령을 목록 형식으로 제공하지 않으려는 경우 (또는 사용할 수없는 경우) 구문 분석 할 수 있습니다.

import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

외부 의존성

외부 의존성을 신경 쓰지 않으면 plumbum을 사용하십시오 .

from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())

최고의 subprocess포장지입니다. 크로스 플랫폼입니다. 즉, Windows 및 Unix 계열 시스템에서 작동합니다. 에 의해 설치pip install plumbum .

또 다른 인기있는 라이브러리는 sh입니다 .

from sh import ifconfig
print(ifconfig('wlan0'))

그러나 shWindows 지원이 중단되었으므로 예전처럼 훌륭하지 않습니다. 로 설치하십시오 pip install sh.


69

호출하는 명령의 출력이 필요한 경우 subprocess.check_output (Python 2.7+)을 사용할 수 있습니다 .

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

매개 변수 도 참고하십시오 .

shell이 True이면 지정된 명령이 셸을 통해 실행됩니다. 이것은 대부분의 시스템 셸에서 제공하는 향상된 제어 흐름을 위해 Python을 주로 사용하면서 셸 파이프, 파일 이름 와일드 카드, 환경 변수 확장 및 사용자의 집으로 ~ 확장과 같은 다른 셸 기능에 편리하게 액세스하려는 경우 유용합니다. 예배 규칙서. 그러나 참고 파이썬 자체의 구현을 제공하는 많은 쉘 등의 기능 (특히, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), 및 shutil).


1
check_output문자열이 아닌 목록 이 필요합니다. 인용 된 공백을 사용하여 통화를 유효하게하지 않는 경우 가장 간단하고 읽기 쉬운 방법은 subprocess.check_output("ls -l /dev/null".split())입니다.
Bruno Bronosky

56

이것이 내가 명령을 실행하는 방법입니다. 이 코드에는 필요한 모든 것이 있습니다

from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()

3
가독성을 높이면 하드 코딩 된 명령에 적합하다고 생각합니다.
Adam Matan

54

최신 정보:

subprocess.run코드가 이전 Python 버전과의 호환성을 유지할 필요가없는 경우 Python 3.5 부터 권장되는 방법 입니다. 보다 일관성 있고 Envoy와 비슷한 사용 편의성을 제공합니다. (배관은 간단하지 않습니다. 방법에 대해서는 이 질문을 참조하십시오 .)

다음 은 문서 의 일부 예입니다 .

프로세스를 실행하십시오.

>>> subprocess.run(["ls", "-l"])  # Doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

실패한 실행시 발생 :

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

캡처 출력 :

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

원래 답변 :

Envoy 시도해 보는 것이 좋습니다 . 하위 프로세스의 래퍼로 , 이전 모듈과 기능 을 대체 하는 것을 목표로 합니다. 특사는 인간의 하위 프로세스입니다.

README의 사용법 예 :

>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''

파이프도 주변에 :

>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[<Response 'uptime'>]


36

파이썬에서 외부 명령 호출

간단한 use를 사용 subprocess.run하면 CompletedProcess객체 를 반환 합니다.

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

왜?

Python 3.5부터 문서는 subprocess.run을 권장합니다 .

서브 프로세스 호출에 권장되는 접근 방식은 처리 할 수있는 모든 사용 사례에 대해 run () 함수를 사용하는 것입니다. 고급 사용 사례의 경우 기본 Popen 인터페이스를 직접 사용할 수 있습니다.

가장 간단한 사용법의 예는 다음과 같습니다. 요청한대로 정확하게 수행합니다.

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

run명령이 성공적으로 완료 될 때까지 기다린 다음 CompletedProcess객체 를 반환 합니다. 대신 TimeoutExpired( timeout=인수 를 주면 ) 또는 CalledProcessError(실패하고 통과하면) 발생할 수 있습니다 check=True.

위 예제에서 알 수 있듯이 stdout 및 stderr은 기본적으로 사용자의 stdout 및 stderr로 파이프됩니다.

반환 된 객체를 검사하고 주어진 명령과 반환 코드를 볼 수 있습니다.

>>> completed_process.args
'python --version'
>>> completed_process.returncode
0

출력 캡처

출력을 캡처하려는 경우 subprocess.PIPE적절한 stderr또는 stdout다음으로 전달할 수 있습니다 .

>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(버전 정보가 stdout 대신 stderr에 배치되는 것이 흥미롭고 약간 반 직관적입니다.)

명령 목록 전달

(질문과 같이) 명령 문자열을 수동으로 제공하는 것에서 프로그래밍 방식으로 작성된 문자열을 제공하는 것으로 쉽게 이동할 수 있습니다. 프로그래밍 방식으로 문자열을 작성하지 마십시오. 잠재적 인 보안 문제입니다. 입력을 신뢰하지 않는다고 가정하는 것이 좋습니다.

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\n'

참고 만 args 위치를 전달해야합니다.

완전한 서명

소스의 실제 서명은 다음과 같습니다 help(run).

def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

popenargs와는 kwargs받는 주어진다 Popen생성자입니다. input바이트 문자열 (또는 인코딩을 지정하는 경우 유니 코드 또는universal_newlines=True서브 프로세스의 stdin에 파이프되는 )이 될 수 있습니다.

설명서는 내가 할 수있는 것보다 더 잘 설명 timeout=하고 있습니다 check=True.

제한 시간 인수는 Popen.communicate ()에 전달됩니다. 제한 시간이 만료되면 하위 프로세스가 종료되고 대기합니다. 하위 프로세스가 종료 된 후 TimeoutExpired 예외가 다시 발생합니다.

check가 true이고 프로세스가 0이 아닌 종료 코드로 종료되면 CalledProcessError 예외가 발생합니다. 해당 예외의 속성은 인수, 종료 코드 및 stdout 및 stderr이 캡처 된 경우 보유합니다.

그리고이 예제 check=True는 내가 생각해 낼 수있는 것보다 낫습니다.

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

확장 된 서명

설명서에 제공된 확장 된 서명은 다음과 같습니다.

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

이는 args 목록 만 위치 적으로 전달해야 함을 나타냅니다. 나머지 인수는 키워드 인수로 전달하십시오.

포펜

Popen대신 사용할 때 ? 나는 논쟁만으로 유스 케이스를 찾는 데 어려움을 겪을 것입니다. Popen그러나 직접 사용 하면 다음을 포함한 방법에 액세스 할 수 있습니다poll 'send_signal', 'terminate'및 'wait'를 .

다음 은 source에Popen 제공된 서명 입니다. 나는 이것이 정보의 가장 정확한 캡슐화라고 생각한다 .help(Popen)

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

하지만 더 유익 문서 :Popen

subprocess.Popen(args, bufsize=-1, executable=None, stdin=None,
                 stdout=None, stderr=None, preexec_fn=None, close_fds=True,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

새 프로세스에서 하위 프로그램을 실행하십시오. POSIX에서 클래스는 os.execvp ()와 유사한 동작을 사용하여 자식 프로그램을 실행합니다. Windows에서 클래스는 Windows CreateProcess () 함수를 사용합니다. Popen에 대한 주장은 다음과 같습니다.

남은 문서를 이해하는 Popen것은 독자를위한 연습으로 남을 것입니다.


기본 프로세스 및 하위 프로세스 간의 양방향 통신의 간단한 예는 여기에서 찾을 수 있습니다 : stackoverflow.com/a/52841475/1349673를
제임스 Hirschorn을

첫 번째 예는 아마도 shell=True명령을 목록으로 전달하거나 더 잘 전달해야합니다.
트리플 리

35

os.system괜찮지 만 날짜가 있습니다. 또한 매우 안전하지 않습니다. 대신을 시도하십시오 subprocess. subprocesssh를 직접 호출하지 않으므로보다 안전합니다.os.system .

더 많은 정보 얻기 여기를 하십시오 .


2
전반적인 권장 사항에 동의하지만 subprocess모든 보안 문제를 제거하지는 않으며 자체적으로 성가신 문제가 있습니다.
tripleee

33

또한이 납은

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns

28

사용하다:

import os

cmd = 'ls -al'

os.system(cmd)

os-이 모듈은 운영 체제 종속 기능을 사용하는 이식 가능한 방법을 제공합니다.

더 많은 os기능을 위해 여기 에 설명서가 있습니다.


2
더 이상 사용되지 않습니다. 사용 서브 프로세스
코리 골드버그

28

다음과 같이 간단 할 수 있습니다.

import os
cmd = "your command"
os.system(cmd)

1
이것은 단점을 지적하지 못하는데, 이는 PEP-324 에 훨씬 더 자세히 설명되어 있습니다. 에 대한 문서는이를 os.system피하기 위해 명시 적으로 권장합니다 subprocess.
tripleee December

25

나는 단순함을 위해 shell_command 를 아주 좋아 합니다. 하위 프로세스 모듈 위에 구축되었습니다.

다음은 설명서의 예입니다.

>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py  shell_command.py  test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0

24

이전에 언급되지 않은 또 다른 차이점이 있습니다.

subprocess.Popen<command>를 하위 프로세스로 실행합니다. 제 경우에는 다른 프로그램 인 <b>와 통신해야하는 <a> 파일을 실행해야합니다.

하위 프로세스를 시도했는데 실행이 성공했습니다. 그러나 <b>은 <a>와 통신 할 수 없습니다. 터미널에서 둘 다 실행할 때 모든 것이 정상입니다.

하나 더 : (참고 : kwrite는 다른 응용 프로그램과 다르게 작동합니다. Firefox에서 아래를 시도하면 결과가 동일하지 않습니다.)

를 시도 os.system("kwrite")하면 사용자가 kwrite를 닫을 때까지 프로그램 흐름이 정지됩니다. 그것을 극복하기 위해 나는 대신 시도했다 os.system(konsole -e kwrite). 이번에는 프로그램이 계속 진행되었지만 kwrite는 콘솔의 하위 프로세스가되었습니다.

누구나 kwrite를 하위 프로세스가 아닌 상태로 실행합니다 (즉, 시스템 모니터에서 트리의 가장 왼쪽 가장자리에 표시되어야 함).


1
"누구든지 kwrite를 하위 프로세스로 실행하지 않는다" 는 것은 무엇을 의미 합니까?
Peter Mortensen 2016 년

23

os.system결과를 저장할 수 없으므로 결과를 일부 목록이나 무언가에 저장하려면 subprocess.call작동합니다.


22

subprocess.check_call반환 값을 테스트하지 않으려는 경우 편리합니다. 오류가 발생하면 예외가 발생합니다.


22

나는 인용 된 문자열의 이스케이프를 처리하기 위해 shlex 와 함께 서브 프로세스 를 사용하는 경향이 있습니다 .

>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)

17

뻔뻔한 플러그, 나는 이것을 위해 라이브러리를 썼다 : P https://github.com/houqp/shell.py

기본적으로 popen 및 shlex의 래퍼입니다. 파이핑 명령도 지원하므로 Python에서 명령을 더 쉽게 연결할 수 있습니다. 따라서 다음과 같은 작업을 수행 할 수 있습니다.

ex('echo hello shell.py') | "awk '{print $2}'"

16

윈도우에서 그냥 가져올 수있는 subprocess모듈을하고 호출하여 외부 명령을 실행 subprocess.Popen(), subprocess.Popen().communicate()그리고 subprocess.Popen().wait()다음과 같이 :

# Python script to run a command line
import subprocess

def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    rc = process.wait()

    if rc != 0:
        print "Error: failed to execute command:", cmd
        print error
    return result
# def

command = "tasklist | grep python"
print "This process detail: \n", execute(command)

산출:

This process detail:
python.exe                     604 RDP-Tcp#0                  4      5,660 K

15

Linux에서는 독립적으로 실행되는 외부 명령을 호출하려는 경우 (python 스크립트가 종료 된 후에도 계속 실행 됨) 작업 스풀러 또는 at 명령 으로 간단한 큐를 사용할 수 있습니다.

작업 스풀러의 예 :

import os
os.system('ts <your-command>')

작업 스풀러 ( ts) 에 대한 참고 사항 :

  1. 다음을 사용하여 실행할 동시 프로세스 수 ( "슬롯")를 설정할 수 있습니다.

    ts -S <number-of-slots>

  2. 설치 ts에는 관리자 권한이 필요하지 않습니다. 간단한 소스를 사용하여 소스에서 다운로드하여 컴파일하고 make경로에 추가하면 완료됩니다.


1
ts에 대한 포인터 at는 약간 유용 하지만 내가 아는 배포판의 표준은 아닙니다 . 아마 언급해야합니다 batch. 다른 곳에서와 같이 os.system()권장 사항은 적어도 subprocess권장되는 대체 항목 이라고 언급해야합니다 .
tripleee

15

Popen을 사용하면 프로 시저의 상태를 확인할 수 있습니다.

from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill()

하위 프로세스를 확인하십시오 .


15

OpenStack Neutron 에서 네트워크 ID를 가져 오려면 다음을 수행하십시오 .

#!/usr/bin/python
import os
netid = "nova net-list | awk '/ External / { print $2 }'"
temp = os.popen(netid).read()  /* Here temp also contains new line (\n) */
networkId = temp.rstrip()
print(networkId)

nova net-list 출력

+--------------------------------------+------------+------+
| ID                                   | Label      | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1      | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External   | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal   | None |
+--------------------------------------+------------+------+

의 출력 인쇄 (NETWORKID)

27a74fcd-37c0-4789-9414-9531b7e3f126

os.popen()2016 년 에는 권장하지 않습니다 . Awk 스크립트는 기본 Python 코드로 쉽게 대체 할 수 있습니다.
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.