python - 제어 - 파이썬 응용 프로그램 실행




파이썬에서 외부 명령 호출하기 (20)

파이썬에서 외부 명령 호출하기

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):

popenargskwargspopenargs 생성자에게 주어집니다. input 은 하위 프로세스의 표준 입력으로 파이프 될 바이트 문자열 (또는 인코딩을 지정하는 경우 유니 코드 또는 universal_newlines=True )이 될 수 있습니다.

설명서는 timeout=check=True 보다 더 잘 설명합니다.

timeout 인수는 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 을 사용할 Popen ? 나는 논쟁만으로 유스 케이스를 찾는데 어려움을 겪을 것이다. 그러나 Popen 직접 사용하면 poll , 'send_signal', 'terminate'및 'wait'등의 메소드에 액세스 할 수 있습니다.

다음 은 소스 에서 주어진 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 에 대한 나머지 문서를 이해하는 것은 독자의 연습 과제로 남겨 둡니다.

파이썬 스크립트 내에서 외부 명령 (예 : 유닉스 쉘 또는 Windows 명령 프롬프트에서 입력 한 것처럼)을 호출하려면 어떻게해야합니까?


최신 정보:

코드가 이전 Python 버전과의 호환성을 유지할 필요가없는 경우 subprocess.runPython 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')

원문 답변 :

나는 https://github.com/kennethreitz/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'>]

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

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

child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

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

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

from subprocess import Popen

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

subprocess.Popen 확인하십시오. subprocess.Popen .


나는 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)

나는 그 단순성 때문에 shell_command 를 아주 좋아한다. 서브 프로세스 모듈 위에 구축됩니다.

다음은 docs의 예제입니다.

>>> 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

나는 항상 다음과 같은 것들을 위해 fabric 을 사용한다.

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

그러나 이것은 좋은 도구 인 것 같습니다 : sh (파이썬 하위 프로세스 인터페이스) .

예를보세요.

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

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

  1. os.system("some_command with args") 명령과 인수를 시스템 쉘에 전달합니다. 이 방법으로 한 번에 여러 명령을 실행하고 파이프와 입출력 방향 재 지정을 설정할 수 있기 때문에 이점이 좋습니다. 예 :

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

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

  2. stream = os.popen("some_command with args")os.system 과 같은 일을 할 것입니다. 단, 프로세스와 관련된 표준 입력 / 출력에 액세스 할 수있는 파일과 유사한 객체를 제공합니다. 모든 3 가지 I / O를 약간 다르게 처리하는 popen의 다른 변종이 있습니다. 모든 것을 문자열로 전달하면 명령이 셸로 전달됩니다. 목록으로 전달하면 아무 것도 피할 걱정할 필요가 없습니다. 설명서를 참조하십시오.

  3. subprocess 모듈의 Popen 클래스입니다. 이것은 os.popen 대체하기위한 것이지만 너무 포괄적이기 때문에 약간 더 복잡하다는 단점이 있습니다. 예를 들어 다음과 같이 말합니다.

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

    대신에:

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

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

  4. subprocess 모듈의 call 함수. 이것은 기본적으로 Popen 클래스와 같으며 동일한 인수를 모두 사용하지만 명령이 완료 될 때까지 대기하고 리턴 코드를 제공합니다. 예 :

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

    설명서를 참조하십시오.

  5. 파이썬 3.5 또는 그 이후 버전을 사용하고 있다면 새로운 subprocess.run 함수를 사용할 수 있습니다.이 함수는 위와 비슷하지만 더욱 유연하며 명령이 실행되면 CompletedProcess 객체를 반환합니다.

  6. os 모듈은 또한 C 프로그램에서 가지고있는 모든 fork / exec / spawn 함수를 가지고 있지만, 직접적으로 사용하는 것은 권하지 않습니다.

subprocess 모듈은 아마도 여러분이 사용하는 모듈이어야합니다.

마침내 셸이 최종 명령을 문자열로 전달하고 모든 명령을 이스케이프 처리해야하는 모든 방법에 대해 알아 두십시오. 전달한 문자열의 일부가 완전히 신뢰할 수없는 경우 보안에 심각한 영향을 미칩니다 . 예를 들어, 사용자가 문자열의 일부 또는 전부를 입력하는 경우. 확신이 없으면 상수와 함께이 메소드 만 사용하십시오. 함축적 인 의미를 부여하려면 다음 코드를 고려하십시오.

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

사용자가 "my mama didnt love me && rm -rf /"라고 입력했다고 상상해보십시오.


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

이것은 기본적으로 popen과 shlex의 래퍼입니다. 또한 파이핑 명령을 지원하므로 파이썬에서 명령을 쉽게 연결할 수 있습니다. 그래서 당신은 다음과 같은 일을 할 수 있습니다 :

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

쉘 대신 이스케이프 처리를하므로 훨씬 안전합니다 : os.system 대신 서브 프로세스 모듈을 사용하는 것이 좋습니다. http://docs.python.org/library/subprocess.html

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

이것은 간단 할 수 있습니다 :

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

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

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()

파이썬으로 외부 명령을 호출 할 수있게 해주는 많은 라이브러리가 있습니다. 각 라이브러리에 대해 설명을하고 외부 명령을 호출하는 예제를 보여 줬습니다. 예제로 사용한 명령은 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.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은 "script-like"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 [email protected]:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')

구조

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

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의 코멘트를 기반으로했습니다.


표준 라이브러리의 하위 프로세스 모듈 을 살펴보십시오.

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

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

공식 문서 에서는 대체 os.system ()에 대한 하위 프로세스 모듈을 권장합니다.

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

하위 프로세스 문서의 " 하위 함수 모듈을 하위 프로세스 모듈로 바꾸기 "섹션에는 유용한 방법이있을 수 있습니다.

하위 프로세스 모듈에 대한 공식 문서 :


호출중인 명령의 출력이 필요하면 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 매개 변수에 유의하십시오.

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



os.system 은 괜찮지 만 날짜는 종류가 다릅니다. 그것은 또한 안전하지 않습니다. 대신 subprocess 사용해보십시오. subprocess 는 sh를 직접 호출하지 않으므로 os.system 보다 안전 os.system .

여기에서 자세한 정보를 얻으십시오.


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


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

작업 스풀러의 예 :

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

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

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

    ts -S <number-of-slots>

  2. 설치 ts에는 관리자 권한이 필요하지 않습니다. 원본에서 간단하게 다운로드하고 컴파일 할 수 있으며 make경로에 추가하면 완료됩니다.


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

명령의 결과를 반환하려면 os.popen 을 사용할 수 있습니다. 그러나이 버전은 하위 프로세스 모듈 을 위해 버전 2.6부터 사용되지 않으며, 다른 답변은 잘 설명되어 있습니다.





external