Wywołanie zewnętrznego polecenia w Pythonie

Jak mogę wywołać zewnętrzne polecenie (tak jakbym wpisał je w powłoce Uniksa lub wierszu polecenia systemu Windows) ze skryptu Pythona?

Author: igaurav, 2008-09-18

30 answers

Spójrz na moduł podprocesu w bibliotece standardowej:

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

Zaletą podprocesu vs. Systemu jest to, że jest bardziej elastyczny (można uzyskać stdout, stderr, "prawdziwy" kod statusu, lepszą obsługę błędów itp...).

Oficjalna dokumentacja zaleca modułpodproces nad alternatywnym systemem operacyjnym.system (): {]}

Modułpodproces zapewnia potężniejsze urządzenia do spawania nowych procesy i pobieranie ich wyników; korzystanie z tego modułu jest lepsze niż korzystanie z tej funkcji [os.system()].

Sekcja "zastępowanie starszych funkcji modułem podprocesu" w dokumentacji podprocesu {8]} może zawierać kilka przydatnych przepisów.

Oficjalna dokumentacja modułu podprocesu :

 3622
Author: David Cournapeau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-03 14:41:52

Oto podsumowanie sposobów wywoływania programów zewnętrznych oraz zalet i wad każdego z nich:

  1. os.system("some_command with args") przekazuje polecenie i argumenty do powłoki systemu. Jest to miłe, ponieważ w ten sposób można uruchomić wiele poleceń naraz i skonfigurować rury i przekierowanie wejścia/wyjścia. Na przykład:

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

    Jednak, chociaż jest to wygodne, musisz ręcznie obsługiwać ucieczkę znaków powłoki, takich jak spacje itp. Z drugiej strony ręcznie, pozwala to również uruchamiać polecenia, które są po prostu komendami powłoki, a nie w rzeczywistości zewnętrznymi programami. Zobacz dokumentację .

  2. stream = os.popen("some_command with args") zrobi to samo co os.system z tym wyjątkiem, że daje obiekt podobny do pliku, który można użyć do uzyskania dostępu do standardowego wejścia/wyjścia dla tego procesu. Istnieją 3 inne warianty popen, które obsługują we / wy nieco inaczej. Jeśli przekazujesz wszystko jako ciąg znaków, wtedy twoje polecenie jest przekazywane do powłoki; jeśli przekazujesz je jako lista wtedy nie musisz się martwić o ucieczkę od czegokolwiek. Zobacz dokumentację .

  3. Klasa Popen modułu subprocess. Ma to na celu zastąpienie os.popen, ale ma tę zaletę, że jest nieco bardziej skomplikowana, ponieważ jest tak kompleksowa. Na przykład:

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

    Zamiast:

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

    Ale miło jest mieć wszystkie opcje w jednej zunifikowanej klasie zamiast 4 różnych funkcji popen. Zobacz też dokumentacja .

  4. Funkcja call z modułu subprocess. Jest to w zasadzie podobne do klasy Popen i pobiera wszystkie te same argumenty, ale po prostu czeka, aż Komenda zakończy się i poda kod powrotu. Na przykład:

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

    Zobacz dokumentację .

  5. Jeśli korzystasz z Pythona 3.5 lub nowszego, możesz użyć nowego subprocess.run funkcja, która jest bardzo podobna do powyższego, ale jeszcze bardziej elastyczna i zwraca a CompletedProcess obiekt po zakończeniu wykonywania polecenia.

  6. Moduł os posiada również wszystkie funkcje fork/exec/spawn, które można mieć w programie C, ale nie polecam ich używać bezpośrednio.

Moduł subprocess powinien być tym, czego używasz.

Na koniec należy pamiętać, że dla wszystkich metod, w których przekazujesz ostateczne polecenie do wykonania przez powłokę jako łańcuch znaków i jesteś odpowiedzialny za jego ucieczkę. są poważne implikacje bezpieczeństwa jeśli jakakolwiek część ciągu, który przekazujesz, nie może być w pełni zaufana. Na przykład, jeśli użytkownik wprowadza jakąś / dowolną część łańcucha. Jeśli nie masz pewności, używaj tych metod tylko ze stałymi. Aby dać Ci podpowiedź o implikacjach rozważ ten kod:

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

I wyobraź sobie, że użytkownik wpisuje " moja mama mnie nie kochała & & rm-rf/".

 2531
Author: Eli Courtwright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-11 19:18:11

Zazwyczaj używam:

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

Możesz robić co chcesz z stdout danymi w rurze. W rzeczywistości, można po prostu pominąć te parametry (stdout= i stderr=) i będzie zachowywać się jak os.system().

 271
Author: EmmEff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-10 13:22:55

Kilka wskazówek na temat odłączenia procesu potomnego od wywołującego (uruchomienie procesu potomnego w tle).

Załóżmy, że chcesz rozpocząć długie zadanie ze skryptu CGI, to znaczy, że proces potomny powinien żyć dłużej niż proces wykonywania skryptu CGI.

Klasyczny przykład z modułu podprocesowego docs To:

import subprocess
import sys

# some code here

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

# some more code here

Chodzi o to, że nie chcesz czekać w linii 'call podprocess' aż do longtask.py jest skończony. Ale nie jest jasne, co się dzieje po linii 'some more code here' z przykładu.

Moją docelową platformą był freebsd, ale rozwój był na windows, więc najpierw stanąłem przed problemem na windows.

W systemie windows (win xp) proces nadrzędny nie zakończy się, dopóki longtask.py zakończył pracę. To nie jest to, czego chcesz w CGI-script. Problem nie jest specyficzny dla Pythona, w społeczności PHP problemy są takie same.

Rozwiązaniem jest przekazanie znacznika tworzenia procesu DETACHED_PROCESS do podstawowa funkcja CreateProcess w win API. Jeśli zdarzy ci się, że masz zainstalowany pywin32, możesz zaimportować flagę z modułu win32process, w przeciwnym razie powinieneś zdefiniować ją samodzielnie:

DETACHED_PROCESS = 0x00000008

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

/* UPD 2015.10.27 @eryksun w komentarzu poniżej zaznaczono, że poprawna semantycznie flaga to CREATE_NEW_CONSOLE (0x00000010) * /

Na freebsd mamy jeszcze jeden problem: gdy proces rodzic jest skończony, kończy również procesy potomne. I nie tego chcesz w Skrypt CGI. Niektóre eksperymenty wykazały, że problemem wydaje się być dzielenie sys.stdout. I rozwiązanie robocze było następujące:

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

Nie sprawdzałem kodu na innych platformach i nie znam przyczyn takiego zachowania na freebsd. Jeśli ktoś wie, proszę podzielić się swoimi pomysłami. Googling przy uruchamianiu procesów w tle w Pythonie nie rzuca jeszcze żadnego światła.

 165
Author: newtover,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-27 21:35:57

Zalecałbym użycie modułu podprocesowego zamiast systemu operacyjnego.system, ponieważ nie powoduje ucieczki powłoki dla Ciebie i dlatego jest o wiele bezpieczniejszy: http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost'])
 103
Author: sirwart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-04 19:46:08
import os
cmd = 'ls -al'
os.system(cmd)

Jeśli chcesz zwrócić wyniki polecenia, możesz użyć os.popen. Jest to jednak przestarzałe od wersji 2.6 na rzecz modułu podprocesu , który dobrze obejmował inne odpowiedzi.

 102
Author: Alexandra Franks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 16:53:05
import os
os.system("your command")

Zauważ, że jest to niebezpieczne, ponieważ polecenie nie jest czyszczone. Pozostawiam to do google dla odpowiedniej dokumentacji na temat modułów " os " i "sys". Istnieje kilka funkcji (exec * I spawn*), które będą robić podobne rzeczy.

 89
Author: nimish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-03 17:10:00

Zawsze używam fabric do takich rzeczy jak:

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

Ale to wydaje się być dobrym narzędziem: sh (Python subprocess interface) .

Spójrz na przykład:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
 54
Author: Jorge E. Cardona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 18:28:23

Sprawdź też bibliotekę Pythona "pexpect".

Pozwala na interaktywne sterowanie zewnętrznymi programami / poleceniami, nawet ssh, ftp, telnet, itp. Możesz po prostu wpisać coś w stylu:

child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

child.expect('(?i)password')
 53
Author: athanassis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 23:02:27

Istnieje wiele różnych bibliotek, które umożliwiają wywoływanie zewnętrznych poleceń za pomocą Pythona. Dla każdej biblioteki podałem opis i pokazałem przykład wywołania zewnętrznego polecenia. Poleceniem, którego użyłem jako przykładu jest ls -l (Lista wszystkich plików). Jeśli chcesz dowiedzieć się więcej o którejkolwiek z wymienionych przeze mnie bibliotek i powiązać dokumentację dla każdej z nich.

Źródła:

Są to wszystkie biblioteki:

Mam nadzieję, że to pomoże Ci podjąć decyzję, z której biblioteki korzystać:)

Podproces

Podproces pozwala na wywołanie zewnętrznego polecenia i podłączyć je do ich rur wejściowych/wyjściowych / błędów (stdin, stdout i stderr). Podproces jest domyślnym wyborem dla uruchamiania poleceń, ale czasami inne moduły są lepsze.

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

System Operacyjny jest używany do "funkcji zależnych od systemu operacyjnego". Może być również używany do wywoływania zewnętrznych poleceń z os.system i os.popen (Uwaga: Istnieje również podproces.popen). system operacyjny zawsze uruchomi powłokę i jest prostą alternatywą dla osób, które nie potrzebują do, lub Nie wiem, jak używać subprocess.run.

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

Sh

SH jest podprocesowym interfejsem, który pozwala wywoływać programy tak, jakby były funkcjami. Jest to przydatne, jeśli chcesz uruchomić polecenie wiele razy.

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

Plumbum jest biblioteką dla" skryptowych " programów Pythona. Możesz wywoływać programy takie jak funkcje jak w sh. Plumbum jest przydatny, jeśli chcesz uruchomić rurociąg bez shell.

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

Pexpect

Pexpect pozwala na odradzanie aplikacji potomnych, kontrolowanie ich i znajdowanie wzorców w ich wynikach. Jest to lepsza alternatywa dla podprocesu dla poleceń, które oczekują tty na Uniksie.

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

Tkanina

Fabric jest biblioteką Pythona 2.5 i 2.7. Pozwala na wykonywanie lokalnych i zdalnych poleceń powłoki. Fabric jest prostą alternatywą dla uruchamiania poleceń w bezpiecznej powłoce (SSH)

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

Envoy

Envoy jest znany jako "podproces dla ludzi". Jest używany jako wygodna owijarka wokół modułu subprocess.
r = envoy.run("ls -l") # Run command
r.std_out # get output

Komendy

commands zawiera funkcje wrappera dla os.popen, ale został usunięty z Pythona 3, ponieważ subprocess jest lepszą alternatywą.

Edycja została oparta na komentarzu J. F. Sebastiana.

 52
Author: Tom Fuller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 23:14:34

Jeśli potrzebujesz wyjścia z wywołanego polecenia, następnie możesz użyć podprocesu .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'

Zwróć również uwagę na parametr powłoki.

Jeśli powłoką jest True, określone polecenie zostanie wykonane przez powłokę. Może to być przydatne, jeśli używasz Pythona głównie do ulepszonego przepływu sterowania, który oferuje w większości powłok systemowych i nadal chcesz wygodny dostęp do innych funkcji powłoki, takich jak rury powłoki, nazwa pliku wildcards, rozszerzenie zmiennej środowiskowej i rozszerzenie ~ do katalogu domowego użytkownika. Należy jednak pamiętać, że sam Python oferuje implementacje wielu funkcji podobnych do powłoki (w szczególności, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), i shutil).

 47
Author: Facundo Casco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-03 20:18:34

Tak uruchamiam moje polecenia. Ten kod ma wszystko, czego potrzebujesz w zasadzie

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()
 42
Author: Usman Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-28 05:44:05

Z Biblioteką Standardową

The Use subprocess module (Python 3):

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

Jest to zalecany standardowy sposób. Jednak bardziej skomplikowane zadania (rury, wyjście, wejście itp.) może być żmudne konstruowanie i pisanie.

Uwaga dotycząca wersji Pythona: jeśli nadal używasz Pythona 2, podproces.call Działa w podobny sposób.

ProTip: shlex.split może pomóc w przetworzeniu polecenia dla run, call, i inni subprocess funkcje w przypadku, gdy nie chcesz (lub nie możesz!) podaj je w formie list:

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

Z Zewnętrznymi Zależnościami

Jeśli nie masz nic przeciwko zewnętrznym zależnościom, użyj plumbum :

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

Jest to najlepsza subprocess owijarka. Jest wieloplatformowy, tzn. działa zarówno na systemach Windows, jak i Unix-podobnych. Install by pip install plumbum.

Kolejną popularną biblioteką jest sh :

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

Jednak sh porzucił wsparcie Dla Windows, więc nie jest tak zajebiście jak kiedyś. Install by pip install sh.

 39
Author: Honza Javorek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 13:55:27

Aktualizacja:

subprocess.run jest zalecanym podejściem od Pythona 3.5 , jeśli twój kod nie musi zachować zgodności z wcześniejszymi wersjami Pythona. Jest bardziej spójny i oferuje podobną łatwość obsługi jak Envoy. (Orurowanie nie jest jednak tak proste. Zobacz to pytanie, jak .)

Oto kilka przykładów z docs.

Uruchom proces:

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

Podniesienie przy nieudanym uruchomieniu:

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

Capture wyjście:

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

Oryginalna ODPOWIEDŹ:

Zalecam wypróbowanie Envoy . Jest to wrapper dla podprocesu, który z kolei ma zastąpić starsze moduły i funkcje. Envoy jest podprocesem dla ludzi.

Przykładowe użycie z 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
''

Fajki też:

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

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

>>> r.history
[<Response 'uptime'>]
 36
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:36

Bez wyjścia wyniku:

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

Z wyjściem wyniku:

import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
 32
Author: Zuckonit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 22:59:14

Https://docs.python.org/2/library/subprocess.html

...lub dla bardzo prostego polecenia:

import os
os.system('cat testfile')
 24
Author: Ben Hoffstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-02 04:00:55

Istnieje również Plumbum

>>> 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
 23
Author: stuckintheshuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-10 17:41:13

os.system jest ok, ale trochę przestarzałe. Nie jest też zbyt bezpieczny. Zamiast tego spróbuj subprocess. subprocess nie wywołuje sh bezpośrednio i dlatego jest bezpieczniejszy niż os.system.

Więcej informacji Tutaj .

 23
Author: Martin W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-10 13:25:05

Użycie:

import os

cmd = 'ls -al'

os.system(cmd)

System Operacyjny-moduł ten zapewnia przenośny sposób korzystania z funkcjonalności zależnej od systemu operacyjnego.

Aby uzyskać więcej funkcji os, tutaj znajduje się dokumentacja.

 22
Author: Priyankara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 23:05:23

To może być takie proste:

import os
cmd = "your command"
os.system(cmd)
 19
Author: Samadi Salahedine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 12:06:53

Wywołanie zewnętrznego polecenia w Pythonie

Proste, użyj subprocess.run, które zwraca CompletedProcess obiekt:

>>> 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)
Dlaczego?

Od wersji Pythona 3.5 dokumentacja zaleca podproces .run :

Zalecanym podejściem do wywoływania podprocesów jest użycie funkcji run () dla wszystkich przypadków użycia, które może obsłużyć. W bardziej zaawansowanych przypadkach można użyć interfejsu Popen bezpośrednio.

Oto przykład najprostsze możliwe użycie - i robi dokładnie tak, jak prosi się:

>>> 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 oczekuje na pomyślne zakończenie polecenia, a następnie zwraca obiekt CompletedProcess. Może zamiast tego podnieść TimeoutExpired (Jeśli podasz mu argument timeout=) lub CalledProcessError (jeśli się nie powiedzie i zdasz check=True).

Jak można wywnioskować z powyższego przykładu, stdout i stderr są domyślnie przesyłane do własnych stdout i stderr.

Możemy sprawdzić zwrócony obiekt i zobaczyć polecenie, które zostało podane i returncode:

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

Przechwytywanie wyjścia

Jeśli chcesz przechwycić wyjście, możesz przekazać {[18] } do odpowiedniego stderr lub 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''

(uważam za interesujące i nieco sprzeczne z intuicją, że informacje o wersji są umieszczane na stderr zamiast na stdout.)

Podaj listę poleceń

Można łatwo przejść od ręcznego dostarczania ciągu poleceń (jak sugeruje pytanie) do dostarczania ciągu zbudowanego programowo. nie buduj łańcuchów programowo.To potencjalny problem bezpieczeństwa. Lepiej założyć, że nie ufasz wkładowi.

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

Uwaga, tylko args powinny być przekazywane pozycyjnie.

Pełny Podpis

Oto faktyczny podpis w źródle i jak pokazano przez help(run):

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

popenargs i kwargs są podane konstruktorowi Popen. input może być ciągiem bajtów (lub unicode, jeśli określi kodowanie lub universal_newlines=True), który będzie przesyłany do podprocesu stdin.

Dokumentacja opisuje timeout= i check=True lepiej niż mogłem:

Argument timeout jest przekazywany do Popen.communicate (). Jeśli timeout / align = "center" bgcolor = "# e0ffe0 " / król Danii / / align = center / Na Wyjątek TimeoutExpired zostanie ponownie podniesiony po zakończeniu procesu potomnego / align = "left" /

Jeśli check jest prawdziwe, a proces kończy pracę z niezerowym kodem wyjścia, a Zostanie wywołany wyjątek CalledProcessError. Atrybuty tego Exception hold argumenty, kod wyjścia oraz stdout i stderr if zostali schwytani.

I ten przykład dla {[17] } jest lepszy niż ten, który mógłbym wymyślić:

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

Rozszerzony Podpis

Oto Rozszerzony podpis podany w dokumentacji:]}
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

Zauważ, że oznacza to, że tylko lista args powinna być przekazywana pozycyjnie. Więc podaj pozostałe argumenty jako argumenty słów kluczowych.

Popen

Kiedy zamiast tego użyj Popen? Trudno byłoby znaleźć przypadek użycia oparty na samych argumentach. Bezpośrednie użycie Popen daje jednak dostęp do jego metod, w tym poll, 'send_signal', 'terminate' i 'wait'.

Oto Popen podpis podany w źródle . Myślę, że jest to najbardziej precyzyjna enkapsulacja informacji (w przeciwieństwie do 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):

Ale bardziej pouczające jest Popen dokumentacja :

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)

Uruchamia program potomny w nowym procesie. W POSIX Klasa używa os.execvp () - podobne zachowanie do wykonania programu potomnego. Na Windows, Klasa używa funkcji Windows CreateProcess (). Argumenty do Popen są następujące.

Zrozumienie pozostałej dokumentacji na Popen zostanie pozostawione jako ćwiczenie dla czytelnika.

 18
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 16:37:52

subprocess.check_call jest to wygodne, jeśli nie chcesz testować wartości zwrotnych. Rzuca wyjątek na każdy błąd.

 16
Author: cdunn2001,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-18 19:21:44

Jest tu inna różnica, o której wcześniej nie wspomniano.

subprocess.Popen wykonuje polecenie jako podproces. W moim przypadku muszę wykonać plik , który musi komunikować się z innym programem, .

Próbowałem podprocesu i wykonanie się powiodło. Jednak nie mógł się komunikować z . Wszystko jest normalne, gdy uruchamiam oba z terminala.

Jeszcze jeden: (Uwaga: kwrite zachowuje się inaczej niż inne aplikacje. Jeśli wypróbujesz poniższe z Firefox, wyniki nie będą takie same.)

Jeśli spróbujesz os.system("kwrite"), przepływ programu zawiesza się, dopóki użytkownik nie zamknie kwrite. Aby przezwyciężyć, że próbowałem zamiast os.system(konsole -e kwrite). Tym razem program nadal działał, ale kwrite stał się podprocesem konsoli.

Każdy uruchomi kwrite nie będący podprocesem (tzn. w monitorze systemowym musi pojawić się na lewej krawędzi drzewa).

 16
Author: Atinc Delican,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-03 20:14:32

os.system nie pozwala na przechowywanie wyników, więc jeśli chcesz przechowywać wyniki w jakiejś liście lub coś subprocess.call działa.

 15
Author: Saurabh Bangad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-11 22:45:35

Zwykle używampodprocesu razem zshlex (do obsługi ucieczki cytowanych łańcuchów):

>>> 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)
 15
Author: Emil Stenström,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-30 14:37:04

Bezwstydny plug, napisałem do tego bibliotekę :P https://github.com/houqp/shell.py

Na razie to w zasadzie opakowanie dla popena i shlexa. Obsługuje również polecenia rurociągów, dzięki czemu można łatwiej łączyć polecenia w Pythonie. Więc możesz robić rzeczy takie jak:
ex('echo hello shell.py') | "awk '{print $2}'"
 13
Author: houqp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-01 20:49:01

Możesz użyć Popen, a następnie sprawdzić status procedury:

from subprocess import Popen

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

Sprawdź podproces.Popen .

 13
Author: admire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-28 23:01:49

Bardzo lubię shell_command za swoją prostotę. Jest zbudowany na module podprocesowym.

Oto przykład z dokumentów:

>>> 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
 13
Author: mdwhatcott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 19:29:34

Aby pobrać identyfikator sieci z neutronu OpenStack:

#!/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)

Wyjście 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 |
+--------------------------------------+------------+------+

Wyjście print (networkId)

27a74fcd-37c0-4789-9414-9531b7e3f126
 12
Author: IRSHAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-20 09:50:01

Pod Linuksem, jeśli chcesz wywołać zewnętrzne polecenie, które będzie działać niezależnie (będzie działać po zakończeniu skryptu Pythona), możesz użyć prostej kolejki jako task spooler lub at

Przykład z task spoolerem:

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

Uwagi o task spooler (ts):

  1. Można ustawić liczbę jednoczesnych procesów, które mają być uruchomione ("sloty") za pomocą:

    ts -S <number-of-slots>

  2. Instalowanie ts nie wymaga uprawnień administratora. Możesz pobrać i skompilować go ze źródła za pomocą prostego make, dodać go do swojej ścieżki i gotowe.

 12
Author: Yuval Atzmon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-27 00:15:34