Jak ukryć wyjście podprocesu w Pythonie 2.7

Używam espeaka na Ubuntu i mam skrypt Pythona 2.7, który wypisuje i wypowiada wiadomość:

import subprocess
text = 'Hello World.'
print text
subprocess.call(['espeak', text])

ESpeak wydaje pożądane dźwięki, ale zaśmieca powłokę pewnymi błędami (ALSA lib..., brak podłączenia gniazda), więc nie mogę łatwo odczytać tego, co zostało wydrukowane wcześniej. Kod wyjścia to 0.

Niestety nie ma udokumentowanej opcji, aby wyłączyć jego zwięzłość, więc szukam sposobu, aby tylko wizualnie ją wyciszyć i utrzymać otwartą powłokę w czystości do dalszej interakcji.

Jak mogę to zrobić?

Author: ferkulat, 2012-06-30

6 answers

Przekierowanie wyjścia do DEVNULL:

import os
import subprocess

FNULL = open(os.devnull, 'w')
retcode = subprocess.call(['echo', 'foo'], stdout=FNULL, stderr=subprocess.STDOUT)

Jest to dokładnie to samo co uruchomienie polecenia powłoki:

retcode = os.system("echo 'foo' &> /dev/null")
 329
Author: jdi,
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-30 01:12:06

Oto bardziej przenośna wersja (dla zabawy, w Twoim przypadku nie jest to konieczne):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from subprocess import Popen, PIPE, STDOUT

try:
    from subprocess import DEVNULL # py3k
except ImportError:
    import os
    DEVNULL = open(os.devnull, 'wb')

text = u"René Descartes"
p = Popen(['espeak', '-b', '1'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
p.communicate(text.encode('utf-8'))
assert p.returncode == 0 # use appropriate for your program error handling here
 73
Author: jfs,
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-30 01:02:41

Użycie subprocess.check_output (nowość w Pythonie 2.7). Spowoduje to wyłączenie standardu stdout i wywoła wyjątek, jeśli polecenie nie powiedzie się. (W rzeczywistości zwraca zawartość stdout, więc możesz użyć tego później w swoim programie, jeśli chcesz.) Przykład:

import subprocess
try:
    subprocess.check_output(['espeak', text])
except subprocess.CalledProcessError:
    # Do something

Możesz także stłumić stderr za pomocą:

    subprocess.check_output(["espeak", text], stderr=subprocess.STDOUT)

W przypadku wcześniejszego niż 2.7, użyj

import os
import subprocess
with open(os.devnull, 'w')  as FNULL:
    try:
        subprocess._check_call(['espeak', text], stdout=FNULL)
    except subprocess.CalledProcessError:
        # Do something

Tutaj możesz stłumić stderr za pomocą

        subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL)
 22
Author: Zags,
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-06 21:13:19

Jeśli przypadkiem używasz modułu podprocesowego w windows (nie jest specyficzny dla tego pytania, ale pasuje do tytułu) z Pythonem 2.7 x i są to tylko błędy, które chcesz stłumić( specyficzne dla tego pytania), możesz zrobić coś takiego:

output = subprocess.check_output(["arp", "-a", "-N", "127.0.0.2"], stderr=subprocess.STDOUT)

Powinieneś być w stanie przetestować powyższy kod na swoim systemie, ale jeśli 127.0.0.2 zdarzy się istnieć w Twojej tabeli arp, możesz po prostu wybrać adres ip, który nie ma nic skojarzonego z nim.

 0
Author: MarkProDev,
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 15:48:43

Od Python3 nie musisz już otwierać devnull i możesz wywołać podproces .DEVNULL .

Twój kod zostanie zaktualizowany jako taki:

import subprocess
text = 'Hello World.'
print text
subprocess.call(['espeak', text], stderr=subprocess.DEVNULL)
 0
Author: Josh Correia,
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-07-23 21:56:35

Dlaczego nie używać poleceń.zamiast tego getoutput ()?

import commands

text = "Mario Balotelli" 
output = 'espeak "%s"' % text
print text
a = commands.getoutput(output)
 -5
Author: lolamontes69,
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-08-31 22:40:28