56 Pytanie: Wywołanie zewnętrznego polecenia w Pythonie

pytanie utworzone w Wed, Apr 24, 2019 12:00 AM

Jak mogę wywołać polecenie zewnętrzne (tak jakbym wpisał je w powłoce systemu Unix lub wierszu polecenia systemu Windows) w skrypcie Python?

    
4297
30 odpowiedzi                              30                         

Spójrz na moduł podprocesu w standardowej bibliotece:

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

Zaletą podprocesu w porównaniu z systemem jest to, że jest bardziej elastyczny (możesz uzyskać stdout, stderr, „prawdziwy” kod statusu, lepszą obsługę błędów, etc ...).

oficjalna dokumentacja zaleca podproces moduł nad alternatywą os.system ():

  

Moduł podproces zapewnia wydajniejsze funkcje do tworzenia nowych procesów i pobierania ich wyników; użycie tego modułu jest lepsze niż użycie tej funkcji [ os.system() ]. p>

Zastępowanie starszych funkcji za pomocą moduł podprocesu ”w dokumentacji podprocesu może zawierać kilka przydatnych przepisów.

Starsze wersje Pythona używają wywołania:

 
import subprocess
subprocess.call(["ls", "-l"])
    
4140
2019-04-01 22: 39: 54Z
  1. Czy istnieje sposób na użycie podstawiania zmiennych? IE Próbowałem zrobić echo $PATH przy użyciu call(["echo", "$PATH"]), ale po prostu powtórzył dosłowny ciąg $PATH zamiast wykonywać jakiekolwiek podstawienie. Wiem, że mogę uzyskać zmienną środowiskową PATH, ale zastanawiam się, czy istnieje prosty sposób, aby polecenie zachowywało się dokładnie tak, jakbym wykonał je w bashu.
    2015-09-01 23: 17: 07Z
  2. @ KevinWheeler Musisz użyć shell=True, aby to działało.
    2015-09-02 20: 38: 24Z
  3. @ KevinWheeler NIE powinieneś używać shell=True, w tym celu Python zawiera os.path.expandvars . W twoim przypadku możesz napisać: os.path.expandvars("$PATH"). @SethMMorton ponownie rozważ swój komentarz - > Dlaczego nie użyć powłoki = True
    2015-11-11 20: 24: 27Z
  4. Aby uprościć przynajmniej koncepcyjnie: n call ("ls -l" .split ())
    2018-06-16 17: 15: 48Z
  5. zapomniałeś powiedzieć, że potrzebuje przynajmniej Pythona 3.5. Nie działa na przykład w pythonie 3.4.3, który jest domyślny dla Ubuntu 14.04 LTS
    2019-02-02 22: 50: 04Z

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 twojego systemu. Jest to miłe, ponieważ można w ten sposób uruchomić wiele poleceń jednocześnie i skonfigurować potoki i przekierowanie wejścia /wyjścia. Na przykład:

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

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

  2. stream = os.popen("some_command with args") zrobi to samo, co os.system, z wyjątkiem tego, że daje obiekt podobny do pliku, którego można użyć do access standardowe wejście /wyjście dla tego procesu. Istnieją 3 inne warianty popen, które wszystkie obsługują i /o nieco inaczej. Jeśli przekażesz wszystko jako łańcuch, twoje polecenie zostanie przekazane do powłoki; jeśli przekażesz je jako listę, nie musisz się martwić, że cokolwiek uciekniesz. Zobacz dokumentację .

  3. Klasa Popen modułu subprocess. Ma to zastąpić os.popen, ale ma tę wadę, że jest nieco bardziej skomplikowane, ponieważ jest tak wszechstronne. Na przykład powiedziałbyś:

     
    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 dokumentację .

  4. Funkcja call z modułu subprocess. Jest to w zasadzie tak samo jak klasa Popen i pobiera wszystkie te same argumenty, ale po prostu czeka, aż polecenie zakończy się i da ci kod powrotu. Na przykład:

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

    Zobacz dokumentację .

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

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

Moduł subprocess powinien być prawdopodobnie tym, którego używasz.

Na koniec pamiętaj, że dla wszystkich metod, w których przekazujesz ostatnią komendę do wykonania przez powłokę jako ciąg znaków i jesteś odpowiedzialny za jej ucieczkę. Istnieją poważne konsekwencje dla bezpieczeństwa , jeśli przekazana część łańcucha nie może być w pełni zaufana. Na przykład, jeśli użytkownik wprowadza część /dowolną część ciągu. Jeśli nie jesteś pewien, używaj tych metod tylko ze stałymi. Aby dać ci podpowiedź implikacji, rozważ ten kod:

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

i wyobraź sobie, że użytkownik wprowadza coś „moja mama mnie nie kochała i amp; i rm -rf /”, która mogłaby usunąć cały system plików.

    
2782
2019-04-28 10: 57: 02Z
  1. 2015-05-26 21: 16: 27Z
  2. Jeśli używasz Pythona 3.5+, użyj subprocess.run(). docs.python.org/3.5/library/subprocess.html#subprocess. uruchom
    2015-10-07 16: 37: 18Z
  3. To, co zwykle trzeba wiedzieć, to co robi się z procesem potomnym STDOUT i STDERR, ponieważ jeśli są ignorowane, w pewnych (dość powszechnych) warunkach, ostatecznie dziecko proces wywoła wywołanie systemowe do zapisu w STDOUT (również STDERR?), które przekroczyłoby bufor wyjściowy przewidziany dla procesu przez system operacyjny, a system operacyjny zablokuje go, dopóki jakiś proces nie odczyta z tego bufora. Więc, przy obecnie zalecanych sposobach, subprocess.run(..), co dokładnie „To nie przechwytuje domyślnie standardowego wyjścia standardowego lub standardowego”. ? A co z subprocess.check_output(..) i STDERR?
    2016-06-01 10: 44: 53Z
  4. @ Pitto tak, ale nie jest to wykonywane przez przykład. Zauważ echo przed łańcuchem przekazanym do Popen? Tak więc pełne polecenie będzie echo my mama didnt love me && rm -rf /.
    2018-09-10 16: 38: 25Z
  5. Prawdopodobnie jest to zła droga. Większość ludzi potrzebuje tylko subprocess.run() lub jej starszego rodzeństwa subprocess.check_call() i in. W przypadkach, w których to nie wystarcza, patrz subprocess.Popen(). os.popen() w ogóle nie powinno się wspominać, albo przyjść nawet po" hackowaniu własny kod fork /exec /spawn ”.
    2018-12-03 06: 00: 46Z

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, za pomocą stdout danych w potoku. W rzeczywistości możesz po prostu pominąć te parametry (stdout= i stderr=) i zachowa się jak os.system().

    
306
2016-12-10 13: 22: 55Z
  1. .readlines() czyta wszystkie wiersze naraz, tzn. blokuje się aż do zakończenia podprocesu (zamyka koniec rury). Aby czytać w czasie rzeczywistym (jeśli nie ma problemów z buforowaniem), możesz: for line in iter(p.stdout.readline, ''): print line,
    2012-11-16 14: 12: 18Z
  2. Czy możesz wyjaśnić, co rozumiesz przez „jeśli nie ma problemów z buforowaniem”? Jeśli proces blokuje się zdecydowanie, wywołanie podprocesu również blokuje się. To samo może się zdarzyć w przypadku mojego oryginalnego przykładu. Co jeszcze może się zdarzyć w odniesieniu do buforowania?
    2012-11-17 13: 25: 15Z
  3. proces potomny może używać buforowania bloków w trybie nieinteraktywnym zamiast buforowania linii, więc p.stdout.readline() (uwaga: nr s na końcu) nie zobaczy żadnych danych dopóki dziecko nie zapełni bufora. Jeśli dziecko nie wygeneruje zbyt wielu danych, wyjście nie będzie w czasie rzeczywistym. Zobacz drugi powód w P: Dlaczego nie po prostu użyć fajki (popen ())? Niektóre obejścia są podane w tej odpowiedzi (pexpect, pty, stdbuf)
    2012-11-17 13: 51: 25Z
  4. problem z buforowaniem ma znaczenie tylko wtedy, gdy chcesz uzyskać dane wyjściowe w czasie rzeczywistym i nie dotyczy twojego kodu, który niczego nie drukuje, dopóki wszystkie dane są odbierane
    2012-11-17 13: 53: 26Z
  5. Ta odpowiedź była dobra jak na swój czas, ale nie powinniśmy już polecać Popen do prostych zadań. To również niepotrzebnie określa shell=True. Wypróbuj jedną z subprocess.run() odpowiedzi.
    2018-12-03 05: 39: 55Z

Niektóre wskazówki dotyczące odłączania procesu potomnego od wywołującego (rozpoczęcie procesu potomnego w tle).

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

Klasycznym przykładem z dokumentów modułu podprocesu jest:

 
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 „wywołanie podprocesu”, dopóki nie zakończy się longtask.py. Ale nie jest jasne, co dzieje się po wierszu „więcej kodu tutaj” z przykładu.

Moja docelowa platforma była freebsd, ale rozwój był w systemie Windows, więc najpierw natrafiłem na problem z oknami.

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

Rozwiązaniem jest przekazanie DETACHED_PROCESS Flaga tworzenia procesu do podstawowej funkcji CreateProcess w Win API. Jeśli zdarzyło ci się zainstalować pywin32, możesz zaimportować flagę z modułu win32process, w przeciwnym razie powinieneś sam go zdefiniować:

 
DETACHED_PROCESS = 0x00000008

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

/* UPD 2015.10.27 @eryksun w komentarzu poniżej zauważa, że ​​poprawną semantycznie flagą jest CREATE_NEW_CONSOLE (0x00000010) * /

Na freebsd mamy inny problem: kiedy proces nadrzędny jest zakończony, kończy również procesy potomne. I to nie jest to, czego chcesz w skrypcie CGI. Niektóre eksperymenty sjak to się stało, że problem polegał na udostępnianiu sys.stdout. Rozwiązaniem roboczym było:

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

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

    
196
2017-07-27 21: 35: 57Z
  1. zauważyłem możliwe dziwactwo przy tworzeniu aplikacji py2exe w pydev + eclipse. udało mi się powiedzieć, że główny skrypt nie został odłączony, ponieważ okno wyjściowe eclipse nie kończyło się; nawet jeśli skrypt zostanie wykonany do końca, nadal czeka na zwrot. ale gdy próbowałem kompilować do pliku wykonywalnego py2exe, pojawia się oczekiwane zachowanie (uruchamia procesy jako odłączone, a następnie zamyka). Nie jestem pewien, ale nazwa pliku wykonywalnego nie znajduje się już na liście procesów. działa to dla wszystkich podejść (os.system („start *”), os.spawnl z os.P_DETACH, subprocs itp.)
    2010-04-09 08: 09: 26Z
  2. możesz również potrzebować flagi CREATE_NEW_PROCESS_GROUP. Zobacz Popen czekający na proces potomny, nawet gdy bezpośrednie dziecko zakończy się
    2012-11-16 14: 16: 42Z
  3. Poniższe informacje są niepoprawne: "[o] n windows (win xp), proces nadrzędny nie zakończy się, dopóki longtask.py nie zakończy pracy". Rodzic wyjdzie normalnie, ale okno konsoli (instancja conhost.exe) zamknie się tylko wtedy, gdy zakończy się ostatni dołączony proces, a dziecko może odziedziczyć konsolę rodzica. Ustawienie DETACHED_PROCESS w creationflags zapobiega temu, uniemożliwiając dziecku dziedziczenie lub tworzenie konsoli. Jeśli zamiast tego chcesz nowej konsoli, użyj CREATE_NEW_CONSOLE (0x00000010).
    2015-10-27 00: 27: 30Z
  4. Nie miałem na myśli, że wykonywanie jako proces odłączony jest nieprawidłowe. To powiedziawszy, może być konieczne ustawienie standardowych uchwytów na pliki, potoki lub os.devnull, ponieważ niektóre programy konsoli wychodzą z błędem w inny sposób. Utwórz nową konsolę, gdy chcesz, aby proces potomny współdziałał z użytkownikiem jednocześnie z procesem nadrzędnym. Próba wykonania obu czynności w jednym oknie byłaby myląca.
    2015-10-27 17: 37: 15Z
  5. czy nie ma sposobu na uruchomienie systemu operacyjnego w tle?
    2019-02-24 19: 05: 29Z

Polecam używanie modułu podprocesu zamiast systemu os.system, ponieważ powoduje on ucieczkę powłoki i dlatego jest o wiele bezpieczniejszy: http://docs.python.org/library/subprocess.html

 
subprocess.call(['ping', 'localhost'])
    
120
2014-04-04 19: 46: 08Z
  1. Jeśli chcesz utworzyć listę z polecenia z parametrami , listę, której można użyć z subprocess, gdy shell=False, a następnie użyj shlex.split po prosty sposób na zrobienie tego docs.python.org/2/library /shlex.html#shlex.split (zalecany sposób według dokumentów docs.python.org/2/library/subprocess.html#popen-constructor )
    2018-09-20 18: 07: 21Z
  2. To jest niepoprawne: " to powłoka ucieka dla ciebie i dlatego jest o wiele bezpieczniejsza ". podproces nie wykonuje ucieczki powłoki, podproces nie przekazuje polecenia przez powłokę, więc nie ma potrzeby ucieczki z powłoki.
    2018-12-04 08: 36: 35Z
 
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óre inne odpowiedzi dobrze pokrywają.

    
119
2016-01-26 16: 53: 05Z
  1. 2014-08-08 00: 22: 35Z
  2. Możesz także zapisać swój wynik za pomocą wywołania os.system, ponieważ działa on tak samo jak powłoka UNIX, jak na przykład os.system ('ls -l > test2.txt ”)
    2017-11-07 23: 19: 20Z
 
import os
os.system("your command")

Zauważ, że jest to niebezpieczne, ponieważ polecenie nie jest czyszczone. Pozostawiam to do Google w celu uzyskania odpowiedniej dokumentacji na temat modułów „os” i „sys”. Istnieje wiele funkcji (exec * i spawn *), które będą robić podobne rzeczy.

    
115
2018-06-03 17: 10: 00Z
  1. Co rozumiesz przez „polecenie nie jest czyszczone” ?
    2018-06-03 17: 10: 31Z
  2. Nie mam pojęcia, co miałem na myśli prawie dekadę temu (sprawdź datę!), ale gdybym musiał zgadywać, byłoby tak, że nie ma sprawdzenia poprawności.
    2018-06-06 16: 01: 34Z
  3. To powinno teraz wskazywać na subprocess jako nieco bardziej uniwersalne i przenośne rozwiązanie. Uruchamianie poleceń zewnętrznych jest oczywiście z natury nieportowalne (musisz się upewnić, że polecenie jest dostępne dla każdej architektury, której potrzebujesz), a przekazywanie danych wejściowych przez użytkownika jako polecenie zewnętrzne jest z natury niebezpieczne.
    2018-12-03 05: 11: 39Z
  4. Zwróć uwagę na znacznik czasu tego faceta: „poprawna” odpowiedź ma 40x głosów i jest odpowiedzią # 1.
    2018-12-03 18: 41: 52Z

Istnieje wiele różnych bibliotek, które pozwalają wywoływać polecenia zewnętrzne w Pythonie. Dla każdej biblioteki podałem opis i pokazałem przykład wywoływania polecenia zewnętrznego. Polecenie, którego użyłem jako przykładu, to ls -l (lista wszystkich plików). Jeśli chcesz dowiedzieć się więcej na temat którejś z bibliotek, które wymieniłem i połączyłem dokumentację każdego z nich.

  

Źródła :

  
    
      

To są wszystkie biblioteki:

    
  

Mam nadzieję, że pomoże ci to podjąć decyzję, której biblioteki użyć :)

  

sprocesowanie

Podproces pozwala wywoływać polecenia zewnętrzne i łączyć je z ich rurami wejścia /wyjścia /błędu (stdin, stdout i stderr). Podproces jest domyślnym wyborem do 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

os jest używany do „funkcji zależnych od systemu operacyjnego”. Może być również używany do wywoływania poleceń zewnętrznych za pomocą os.system i os.popen (Uwaga: istnieje również podproces.popen). os zawsze uruchamia powłokę i jest prostą alternatywą dla osób, które nie muszą lub nie wiedzą 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 to interfejs podprocesu, 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 to biblioteka dla „skryptowych” programów Pythona. Możesz wywoływać programy takie jak funkcje jak w sh. Plumbum jest przydatny, jeśli chcesz uruchomić potok bez powłoki.

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

<_actionpexpect>

pexpect pozwala na tworzenie aplikacji potomnych, kontrolowanie ich i znajdowanie wzorców w ich wynikach. Jest to lepsza alternatywa dla przetwarzania podprocesów, które oczekują tty na Uniksie.

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

fabryka

Tkanina

to biblioteka Pythona 2.5 i 2.7. Pozwala na wykonywanie lokalnych i zdalnych poleceń powłoki. Fabric to prosta alternatywa do 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
  

pomoc

wysłannik jest znany jako „podproces dla ludzi”. Jest on używany jako opakowanie wygody wokół modułu subprocess.

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

commands zawiera funkcje opakowujące dla os.popen, ale zostało usunięte z Pythona 3, ponieważ subprocess jest lepszą alternatywą.

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

    
72
2017-05-28 23: 14: 34Z

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 (interfejs podprocesu Pythona) .

Spójrz na przykład:

 
from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
    
64
2013-07-23 18: 28: 23Z

Sprawdź także bibliotekę Pythona „pexpect”.

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

 
child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

child.expect('(?i)password')
    
63
2017-05-28 23: 02: 27Z

Jeśli potrzebujesz danych wyjściowych komendy, którą wywołujesz, następnie możesz użyć 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'

Zwróć także uwagę na parametr powłoka . p>

  

Jeśli powłoka ma True, określone polecenie zostanie wykonane przez powłokę. Może to być przydatne, jeśli używasz Pythona głównie do rozszerzonego przepływu sterowania oferowanego przez większość powłok systemowych i nadal chcesz wygodnego dostępu do innych funkcji powłoki, takich jak rury powłoki, symbole wieloznaczne nazw plików, rozszerzanie zmiennych środowiskowych i rozszerzanie ~ do domu użytkownika informator. 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).

    
59
2018-06-03 20: 18: 34Z
  1. Zauważ, że check_output wymaga listy, a nie łańcucha. Jeśli nie polegasz na cytowanych przestrzeniach, aby twoje połączenie było ważne, najprostszym i najbardziej czytelnym sposobem jest subprocess.check_output("ls -l /dev/null".split()).
    2018-01-30 18: 18: 54Z

Z biblioteką standardową

The Użyj modułu podprocesu (Python 3):

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

Jest to zalecany standardowy sposób. Jednak bardziej skomplikowane zadania (potoki, dane wyjściowe, dane wejściowe itp.) Mogą być żmudne w konstruowaniu i pisaniu.

Uwaga na temat wersji Pythona: Jeśli nadal używasz Pythona 2, shlex.split może pomóc musisz przeanalizować komendę dla run, call i innych funkcji subprocess w przypadku, gdy nie chcesz (lub nie możesz!) udostępnić ich w formie list:

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

Z zależnościami zewnętrznymi

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

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

To najlepsze opakowanie subprocess. Jest to platforma wieloplatformowa, tzn. Działa zarówno w systemach Windows, jak i systemach uniksowych. Zainstaluj przez pip install plumbum.

Inną popularną biblioteką jest sh :

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

Jednak sh porzucił obsługę Windows, więc nie jest tak niesamowity jak kiedyś. Zainstaluj przez pip install sh.

    
56
2018-09-19 13: 55: 27Z

W ten sposób uruchamiam moje polecenia. Ten kod ma wszystko, czego potrzebujesz bardzo

 
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()
    
49
2012-10-28 05: 44: 05Z
  1. Przekazywanie poleceń jako ciągów jest zazwyczaj złym pomysłem
    2013-07-23 18: 29: 11Z
  2. Sądzę, że jest to dopuszczalne dla zakodowanych na stałe poleceń, jeśli zwiększa czytelność.
    2014-04-02 13: 07: 44Z

Aktualizacja:

subprocess.run to zalecane podejście od wersji Python 3.5 , jeśli Twój kod nie musi być zgodny z wcześniejszymi wersjami Pythona. Jest bardziej spójny i oferuje podobną łatwość użycia jak wysłannik. (Piping nie jest jednak tak prosty. Zobacz to pytanie, w jaki sposób ).

Oto kilka przykładów z dokumentów .

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

Wyjście przechwytywania:

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

Polecam wypróbowanie Wysłannika . To wrapper dla podprocesu, który z kolei ma na celu zastąpienie starszych modułów i funkcji . Wysłannik jest podprocesem dla ludzi.

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

Pipe rzeczy też:

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

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

>>> r.history
[<Response 'uptime'>]
    
45
2017-05-23 12: 26: 36Z

Bez wyniku wyniku:

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

Z wynikiem wyniku:

 
import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
    
37
2017-05-28 22: 59: 14Z
  1. commands nie jest już dostępny w Pythonie 3. Wolisz subprocess ponad os.system()
    2018-12-03 05: 33: 09Z

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

... lub bardzo proste polecenie:

 
import os
os.system('cat testfile')
    
32
2014-11-02 04: 00: 55Z

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
    
30
2014-10-10 17: 41: 13Z

os.system jest OK, ale trochę przestarzały. To również nie jest zbyt bezpieczne. Zamiast tego spróbuj subprocess. subprocess nie wywołuje sh bezpośrednio, a zatem jest bezpieczniejszy niż os.system.

Uzyskaj więcej informacji tutaj .

    
29
2016-12-10 13: 25: 05Z
  1. Chociaż zgadzam się z ogólną rekomendacją, subprocess nie usuwa wszystkich problemów związanych z bezpieczeństwem i ma kilka nieznośnych problemów.
    2018-12-03 05: 36: 59Z
  

Wywoływanie zewnętrznego polecenia w Pythonie

Prosty, użyj subprocess.run, który 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?

W Pythonie 3.5 dokumentacja zaleca subprocess.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 przypadku bardziej zaawansowanych zastosowań podstawowy interfejs Popen może być używany bezpośrednio.

Oto przykład najprostszego możliwego użycia - i robi to dokładnie tak, jak zostało to zadane:

 
>>> 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 czeka na pomyślne zakończenie polecenia, a następnie zwraca obiekt CompletedProcess. Zamiast tego może podbić TimeoutExpired (jeśli dasz mu timeout= argumentów) lub CalledProcessError (jeśli ci się nie uda i zdasz check=True).

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

Możemy sprawdzić zwrócony obiekt i zobaczyć podane polecenie oraz kod powrotu:

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

Przechwytywanie danych wyjściowych

Jeśli chcesz przechwycić dane wyjściowe, możesz przekazać subprocess.PIPE 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 w stderr zamiast stdout.)

Podaj listę poleceń

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

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

Zauważ, że tylko args powinno zostać przekazane w pozycji.

Pełny podpis

Oto rzeczywisty podpis w źródle i jak pokazuje help(run):

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

popenargs i kwargs są przekazywane konstruktorowi Popen. input może być ciągiem bajtów (lub unicode, jeśli określono kodowanie lub universal_newlines=True), które zostaną potokowane do standardowego podprocesu.

Dokumentacja opisuje lepiej timeout= i check=True niż ja:

  

Argument timeout jest przekazywany do Popen.communicate (). Jeśli limit czasu   wygasa, proces potomny zostanie zabity i będzie czekał. The   Wyjątek TimeoutExpired zostanie ponownie podniesiony po tym, jak dziecko process ma   zakończone.

     

Jeśli sprawdzanie jest prawdziwe, a proces kończy działanie z niezerowym kodem wyjścia, a   Wywołany zostanie wyjątek CalledProcessError. Atrybuty tego   wyjątek przechowuje argumenty, kod wyjścia i stdout i stderr if   zostali schwytani.

i ten przykład dla check=True jest lepszy niż ten, który mogłem 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, jak podano 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 wskazuje to, że tylko lista argumentów powinna być przekazywana w pozycji. Podaj pozostałe argumenty jako argumenty słowa kluczowego.

Popen

Kiedy używasz Popen? Trudno byłoby mi znaleźć przypadek użycia oparty na samych argumentach. Bezpośrednie użycie Popen dałoby ci jednak dostęp do jego metod, w tym poll, „send_signal”, „terminate” i „wait”.

Oto podpis Popen 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 więcej informacji ma dokumentacja 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)
     

Wykonaj program potomny w nowym procesie. W POSIX klasa używa   os.execvp () - zachowanie podobne do wykonywania programu potomnego. W systemie Windows   klasa używa funkcji Windows CreateProcess (). Argumenty do   Popen są następujące.

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

    
28
2017-10-18 16: 37: 52Z
  1. Prosty przykład dwukierunkowej komunikacji między podstawowym procesem a podprocesem można znaleźć tutaj: stackoverflow.com/a/52841475/1349673
    2018-10-16 18: 05: 17Z
  2. Pierwszy przykład powinien prawdopodobnie mieć shell=True lub (jeszcze lepiej) przekazać polecenie jako listę.
    2018-12-03 05: 16: 05Z

Użyj:

 
import os

cmd = 'ls -al'

os.system(cmd)

os - Ten moduł zapewnia przenośny sposób korzystania z funkcji zależnych od systemu operacyjnego.

Więcej funkcji os, tutaj to dokumentacja.

    
25
2017-05-28 23: 05: 23Z
  1. jest również przestarzały. użyj podprocesu
    2015-12-09 18: 13: 59Z

To może być takie proste:

 
import os
cmd = "your command"
os.system(cmd)
    
25
2018-06-08 12: 06: 53Z
  1. To nie wskazuje wad, które są wyjaśnione bardziej szczegółowo w PEP-324 . Dokumentacja os.system wyraźnie zaleca unikanie tego na korzyść subprocess.
    2018-12-03 05: 02: 26Z

użyj modułu os

 
import os
os.system("your command")

np.

 
import os
os.system("ifconfig")
    
21
2018-07-27 08: 10: 20Z
  1. Powoduje to powtórzenie (nieco) bardziej szczegółowej odpowiedzi z poprzedniego kwietnia, która jednak również nie powiedzie sięwyrzuć zastrzeżenia.
    2018-12-03 04: 59: 29Z

subprocess.check_call jest wygodny, jeśli nie chcesz testować wartości zwracanych. Zgłasza wyjątek przy każdym błędzie.

    
20
2011-01-18 19: 21: 44Z

Zazwyczaj korzystam z podprocesu razem z shlex (aby obsłużyć uciekanie cytowanych ciągó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)
    
20
2014-04-30 14: 37: 04Z

Jest jeszcze jedna różnica, o której wcześniej nie wspomniano.

subprocess.Popen wykonuje komendę < > jako podproces. W moim przypadku muszę wykonać plik < a > który musi komunikować się z innym programem, < b &gt ;.

Próbowałem podprocesu, a wykonanie powiodło się. Jednak < b > nie mógł komunikować się z < a &gt ;. Wszystko jest normalne, gdy uruchamiam oba z terminala.

Jeszcze jedno: (UWAGA: kwrite zachowuje się inaczej niż w innych aplikacjach. Jeśli wypróbujesz poniżej z Firefoksem, wyniki nie będą takie same.)

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

Każdy uruchamia kwrite nie będący podprocesem (tzn. na monitorze systemowym musi pojawić się na skraju lewej strony drzewa).

    
20
2018-06-03 20: 14: 32Z
  1. Co masz na myśli mówiąc „Ktoś uruchamia kwrite nie będący podprocesem” ?
    2018-06-03 20: 14: 54Z

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

    
19
2012-06-11 22: 45: 35Z

Bardzo podoba mi się polecenie shell_command ze względu na jego prostotę. Jest zbudowany na module podprocesu.

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
    
19
2017-10-24 19: 29: 34Z

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

Jest to w zasadzie opakowanie na popen i shlex. Obsługuje również polecenia pipingu, dzięki czemu można łatwiej łączyć polecenia w Pythonie. Więc możesz robić takie rzeczy jak:

 
ex('echo hello shell.py') | "awk '{print $2}'"
    
16
2014-05-01 20: 49: 01Z

W Linuksie, na wypadek gdybyś chciał wywołać komendę zewnętrzną, która zostanie wykonana niezależnie (będzie działać po zakończeniu skryptu Pythona), możesz użyć prostej kolejki jako bufor zadań lub 15

2016-11-27 00: 15: 34Z
  1. ts nie jest standardem w żadnej znanej mi dystrybucji, chociaż wskaźnik do at jest lekko użyteczny. Powinieneś też wspomnieć o batch. Tak jak gdzie indziej, zalecenie os.system() powinno przynajmniej wspomnieć, że subprocess jest zalecanym zamiennikiem.
    2018-12-03 05: 43: 45Z

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

 
from subprocess import Popen

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

Sprawdź subprocess.Popen .

    
14
2017-05-28 23: 01: 49Z
źródło umieszczone tutaj