2012-11-15 6 views
16

Tak więc zauważyłem subprocess.call podczas oczekiwania na zakończenie polecenia, zanim przejdę do skryptu Pythona, nie mam możliwości uzyskania standardowego wyjścia, z wyjątkiem subprocess.Popen. Czy są jakieś alternatywne wywołania funkcji, które będą czekać, aż się skończą? (Próbowałem też Popen.wait)Python subprocess.call i subprocess.Popen stdout

UWAGA: Staram się unikać os.system zadzwoń

result = subprocess.Popen([commands..., 
         self.tmpfile.path()], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
out, err = result.communicate() 
print out+"HIHIHI" 

mój wynik:

HIHIHI 

UWAGA: Próbuję uruchomić wine z tym.

+1

* subprocess.call() * może być użyty do odczytu/err. [sprawdź instrukcję] (http://docs.python.org/2/library/subprocess.html). upewnij się, że polecenie nie generuje dużej ilości danych wyjściowych. – tuxuday

Odpowiedz

46

Używam poniższej konstrukcji, chociaż możesz uniknąć shell=True. To daje komunikat wyjściowy i błędu dla każdego polecenia, a kod błędu, a także:

process = subprocess.Popen(cmd, shell=True, 
          stdout=subprocess.PIPE, 
          stderr=subprocess.PIPE) 

# wait for the process to terminate 
out, err = process.communicate() 
errcode = process.returncode 
+0

Próbowałem tego i nadal otrzymuję puste wyniki: nie jestem całkowicie pewien, co robię źle. –

+2

Co to jest zawartość 'cmd'? – Alex

+0

@Alex cmd musi być poleceniem, które chcesz wykonać. – NeoMorfeo

10

Jeśli proces daje ogromny stdout i nie stderr, communicate() może być niewłaściwy sposób, aby przejść z powodu ograniczeń pamięci.

Zamiast

process = subprocess.Popen(cmd, shell=True, 
          stdout=subprocess.PIPE, 
          stderr=subprocess.PIPE) 

# wait for the process to terminate 
for line in process.stdout: do_something(line) 
errcode = process.returncode 

może być droga.

process.stdout jest obiektem plikopodobnym które można traktować jak każdego innego takiego obiektu, głównie:

  • można read() z niego
  • można readline() od niego i
  • można iterować to.

To ostatnie jest to, co robię powyżej, aby uzyskać zawartość linii po linii.

+1

Czy możesz mi wyjaśnić, co robi pętla for? –

+0

@ Stupid.Fat.Cat Odczytuje 'stdout' wyprodukowany z linii proces po linii i przetwarza każdą linię. – glglgl

+0

Otrzymuję 'ValueError: operacja I/O na zamkniętym pliku' dla operacji' dla linii w process.stdout' – Yash89

11
subprocess.check_output(...) 

dzwoni proces, podnosi, jeśli jego kod błędu jest niezerowy, iw przeciwnym razie zwraca jego standardowe wyjście. To tylko szybki skrót, więc nie musisz się martwić o rzeczy i rzeczy.

+0

Ma to problemy z winem. Przepraszam, dodam to do mojego pytania. –

+3

To jest świetna funkcja, ale tylko w Pythonie 2.7 lub nowszym. – Gourneau

1

chciałbym spróbować czegoś takiego:

#!/usr/bin/python 
from __future__ import print_function 

import shlex 
from subprocess import Popen, PIPE 

def shlep(cmd): 
    '''shlex split and popen 
    ''' 
    parsed_cmd = shlex.split(cmd) 
    ## if parsed_cmd[0] not in approved_commands: 
    ## raise ValueError, "Bad User! No output for you!" 
    proc = Popen(parsed_command, stdout=PIPE, stderr=PIPE) 
    out, err = proc.communicate() 
    return (proc.returncode, out, err) 

... Innymi słowy niech shlex.split() zrobić większość prac. NIE próbowałbym parsować wiersza poleceń powłoki, wyszukiwać operatorów rur i konfigurować własnego potoku. Jeśli masz zamiar to zrobić, będziesz musiał napisać pełny parser składni powłoki, a skończysz robiąc strasznie dużo kanalizacji.

Oczywiście pojawia się pytanie, dlaczego nie wystarczy użyć POPEN z powłoką = true opcji (słowo kluczowe)? To pozwoli ci przekazać ciąg (bez dzielenia i analizowania) do powłoki i nadal zbierać wyniki do obsługi, jak chcesz. Mój przykład tutaj nie przetwarza żadnych potoków, odsunięć, przekierowań deskryptorów plików itp., Które mogą znajdować się w poleceniu, wszystkie pojawią się jako argumenty dosłowne w poleceniu. W związku z tym jest jeszcze bezpieczniej niż działa z shell = True ...Podałem głupi przykład sprawdzenia polecenia w odniesieniu do jakiegoś słownika lub zestawu "zatwierdzonych poleceń" - przez to bardziej sensownym byłoby normalizowanie go na ścieżce absolutnej, chyba że masz zamiar wymagać, aby argumenty były normalizowane przed przekazywanie ciągu poleceń do tej funkcji.

+0

Podoba mi się ten przykład, zwracając uwagę na shlex jako właściwy sposób analizowania danych z linii poleceń. Humor również w tym przykładzie (shlep() i komentarze wyjątków). :) –