프로그램을 실행하거나 시스템 명령을 호출하는 방법은 무엇입니까?


질문

 

Python 스크립트 내에서 외부 명령 (UNIX 셸 또는 Windows 명령 프롬프트에서 입력 한 것처럼)을 어떻게 호출합니까?


답변

 

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

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

OS.System을 통해 하위 프로세스의 장점은 더 유연하다는 것입니다 (STDOUT, stderr, "실제"상태 코드, 더 나은 오류 처리 등을 얻을 수 있습니다 ...).

OS.System 문서조차도 대신 하위 프로세스를 사용하는 것이 좋습니다.

서브 프로세스 모듈은 새로운 프로세스를 산출하고 결과를 검색하는보다 강력한 기능을 제공합니다.해당 모듈을 사용하는 것이이 기능을 사용하는 것이 바람직합니다.도움이되는 조리법의 서브 프로세스 문서의 하위 프로세스 문서의 하위 프로세스 모듈 섹션을 사용하여 이전 기능 교체를 참조하십시오.

Python 3.4 및 이전 버전에서는 .run 대신 subprocess.call을 사용하십시오.

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


답변

이점과 단점을 포함하여 외부 프로그램을 호출하는 방법 요약 :

  1. os.system passes the command and arguments to your system's shell. This is nice because you can actually run multiple commands at once in this manner and set up pipes and input/output redirection. For example:

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

    However, while this is convenient, you have to manually handle the escaping of shell characters such as spaces, et cetera. On the other hand, this also lets you run commands which are simply shell commands and not actually external programs.

  2. os.popen will do the same thing as os.system except that it gives you a file-like object that you can use to access standard input/output for that process. There are 3 other variants of popen that all handle the i/o slightly differently. If you pass everything as a string, then your command is passed to the shell; if you pass them as a list then you don't need to worry about escaping anything. Example:

    print(os.popen("ls -l").read())
    
  3. subprocess.Popen. This is intended as a replacement for os.popen, but has the downside of being slightly more complicated by virtue of being so comprehensive. For example, you'd say:

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

    instead of

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

    but it is nice to have all of the options there in one unified class instead of 4 different popen functions. See the documentation.

  4. subprocess.call. This is basically just like the Popen class and takes all of the same arguments, but it simply waits until the command completes and gives you the return code. For example:

    return_code = subprocess.call("echo Hello World", shell=True)
    
  5. subprocess.run. Python 3.5+ only. Similar to the above but even more flexible and returns a CompletedProcess object when the command finishes executing.

  6. os.fork, os.exec, os.spawn are similar to their C language counterparts, but I don't recommend using them directly.

하위 프로세스 모듈은 아마도 사용하는 것일 수 있습니다.

마지막으로, 쉘에 의해 쉘에 의해 실행되도록 최종 명령을 전달하는 모든 메소드에서는 이스케이프를 탈출 할 책임이 있습니다.통과하는 문자열의 일부가 완전히 신뢰할 수 없으면 심각한 보안 영향이 있습니다.예를 들어 사용자가 문자열의 일부 / 일부를 입력하는 경우입니다.확실하지 않은 경우 이러한 방법 만 상수로 사용하십시오.시사점의 힌트를 제공하려면이 코드를 고려하십시오.

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

그리고 사용자가 전체 파일 시스템을 지울 수있는 "My Mama Didnt Love Me && rm -rf /"라는 무언가를 입력한다고 상상해보십시오.



답변

일반적인 구현 :

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 ()처럼 작동 할 수 있습니다.



답변

일부 힌트는 호출 중 하나 (백그라운드에서 자식 프로세스 시작)에서 자식 프로세스를 분리하는 데 힌트를 힌트합니다.

CGI 스크립트에서 긴 작업을 시작하도록하려면 가정하십시오.즉, 자식 프로세스는 CGI 스크립트 실행 프로세스보다 오래 살아야합니다.

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

import subprocess
import sys

# Some code here

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

# Some more code here

여기에있는 아이디어는 longtask.py가 끝날 때까지 '호출 하위 프로세스'라인에서 기다리고 싶지 않다는 것입니다.그러나이 예에서는 '일부 코드가 더 많은 코드'라인 이후 일어나는 일이 아닙니다.

내 대상 플랫폼은 FreeBSD 였지만 개발은 창문에 있었으므로 먼저 Windows에서 문제가 발생했습니다.

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

솔루션은 Detached_Process 프로세스 생성 플래그를 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에서의 행동의 이유를 알지 못합니다.누군가가 알고 있으면 아이디어를 공유하십시오.파이썬의 배경 프로세스를 시작하는 데 Googling은 아직 빛을 밝히지 않습니다.



답변

import os
os.system("your command")

명령이 청소되지 않으므로 위험합니다.'OS'및 'SYS'모듈에 대한 관련 문서를 Google에 게 구글에 두십시오.비슷한 일을 할 수있는 기능 (exec * 및 spawn *)이 있습니다.



답변

쉘이 탈출하고 훨씬 더 안전하기 때문에 OS.System 대신 하위 프로세스 모듈을 사용하는 것이 좋습니다.

subprocess.call(['ping', 'localhost'])
출처:https://stackoverflow.com/questions/89228/how-to-execute-a-program-or-call-a-system-command