2011-12-16 3 views
35

Czy istnieje wersja subprocess.call, która może uruchomić polecenie bez drukowania na standardowe wyjście, lub sposób blokowania jego standardowych wiadomości wyjściowych?Czy istnieje cicha wersja podprocesu?

+0

Ściśle związane http://stackoverflow.com/questions/5495078/how-do-you-discard-subprocess-output-in-python, w szczególności ze względu na wywołanie używa Popen. –

+0

pokrewne: [Jak ukryć wyjście podprocesu w Pythonie 2.7] (http://stackoverflow.com/q/11269575/4279) – jfs

Odpowiedz

40

Tak. Przekieruj jego stdout do /dev/null.

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb')) 
+1

'Popen' nie jest odmianą' call'. To zupełnie inna funkcja. – jwg

+1

Masz rację. Jednak Popen i call mają bardzo podobne argumenty, więc te rozwiązania działają dla obu. Przesłałem zmianę. – jhrf

+4

Zauważ, że z Python ver. 3.3 w rzeczywistości istnieje 'subprocess.DEVNULL', który może być użyty zamiast' open (os.devnull, 'wb') '. – EquipDev

19

Często ten rodzaj pogawędki jest na stderr, więc możesz też chcieć to uciszyć. Oto mój przykład:

from subprocess import call, DEVNULL 
return_code = call(args, stderr=DEVNULL, stdout=DEVNULL) 

Uwaga:subprocess.DEVNULL jest dostępny od Pythona 3.3. Jeśli nadal na Pythonie 2:

import os 

with open(os.devnull, 'w') as shutup: 
    return_code = call(args, stdout=shutup, stderr=shutup) 
+0

zauważając, że nie ma odpowiedzi na temat używania 'startupinfo', jak pokazano tutaj: http://code.activestate.com/recipes/409002-launching-a-subprocess-without-a-onsole-window/, aby uniknąć migania okna podczas pracy python z konsoli –

+0

python 3 ma teraz 'subprocess.DEVNULL' (ale twoja odpowiedź ma 7 lat) –

+0

@ Jean-FrançoisFabre Było to już wspomniane w komentarzu do zaakceptowanej odpowiedzi. W każdym razie, zredagowałem to teraz, dzięki za sugestię. – wim

10

subprocess.call przyjąć również przekierowań stdin/stdout/stderr:

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb')) 
+2

[The docs] (http://docs.python.org/2/library/subprocess.html#subprocess.call) wyraźnie mówią "Nie używaj stdout = PIPE lub stderr = PIPE z tą funkcją." – mpen

+6

open() nie zwraca PIPE, PIPE oznacza "subprocess.PIPE", który można odczytać z drugiego końca w programie. Otwarta na 'os.devnull' nie spowoduje problemu, ponieważ nie ma dna w tym pliku z czarną dziurą, bufor nigdy nie zostanie zapełniony. – BOYPT

+0

Ah. To ma sens. Dziękuję Ci! Nie chciałem używać "Popena", ponieważ zwraca on proces zamiast kodu statusu. – mpen

1

Jest to przepis używam dużo: Call subprocess i zebrać dane wyjściowe, a gdy polecenie powiedzie się odrzucić dane wyjściowe, ale gdy się nie powiedzie wydrukuj dane wyjściowe.

import subprocess as sp 
import sys 

if "print" in __builtins__.__dict__: 
    prn = __builtins__.__dict__["print"] 
else: 
    def prn(*args, **kwargs): 
     """ 
     prn(value, ..., sep=' ', end='\\n', file=sys.stdout) 
     Works just like the print function in Python 3.x but can be used in 2.x. 

     Prints the values to a stream, or to sys.stdout by default. 
     Optional keyword arguments: 
     file: a file-like object (stream); defaults to the current sys.stdout. 
     sep: string inserted between values, default a space. 
     end: string appended after the last value, default a newline. 
     """ 
     sep = kwargs.get("sep", ' ') 
     end = kwargs.get("end", '\n') 
     file = kwargs.get("file", sys.stdout) 

     s = sep.join(str(x) for x in args) + end 
     file.write(s) 


def rc_run_cmd_basic(lst_cmd, verbose=False, silent=False): 
    if silent and verbose: 
     raise ValueError("cannot specify both verbose and silent as true") 

    p = sp.Popen(lst_cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE) 
    tup_output = p.communicate() 

    s_cmd = ' '.join(lst_cmd) 
    if verbose: 
     prn() 
     prn("command: '%s'\n" % s_cmd) 

     if 0 != p.returncode: 
      prn() 
      prn("Command failed with code %d:" % p.returncode) 
     else: 
      prn("Command succeeded! code %d" % p.returncode) 
    if verbose: 
     prn("Output for: " + s_cmd) 
     prn(tup_output[0]) 
     prn() 
    if not silent and 0 != p.returncode: 
     prn("Error output for: " + s_cmd) 
     prn(tup_output[1]) 
     prn() 

    return p.returncode 
0

Używam podprocesów.check_output w takich przypadkach i upuść wartość zwracaną. Możesz dodać komentarz do swojego kodu stwierdzającego, dlaczego używasz check_output zamiast check_call. check_output jest również ładniejszy, gdy wystąpi awaria i jesteś zainteresowany wyjściem błędu. Przykładowy kod poniżej. Dane wyjściowe są widoczne tylko po odkomentowaniu linii drukowania. Jeśli polecenie nie powiedzie się, zostanie zgłoszony wyjątek.

import subprocess 
ret = subprocess.check_output(["cat", "/tmp/1"]) 
#print ret 
+0

W jaki sposób upuszczenie wartości zwracanej powoduje, że wyjście nie staje się standardowe? – Emre

+0

subprocess.check_output ma przechwycić dane wyjściowe i je zwrócić. Czy widzisz inne zachowanie? –

+0

Przechwytywanie i ignorowanie utworów, ale powoduje utratę pamięci na przechwyconej wartości, która nigdy nie jest używana. Właściwe odrzucanie danych wyjściowych jest bardziej niezawodne. – tripleee