Как скрыть вывод подпроцесса в Python 2.7

Я использую eSpeak в Ubuntu и у меня есть скрипт Python 2.7, который печатает и произносит сообщение:

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

eSpeak производит желаемые звуки, но загромождает оболочку некоторыми ошибками (ALSA lib..., нет подключения к сокету), поэтому я не могу легко прочитать то, что было напечатано ранее. Код выхода 0.

К сожалению, нет задокументированной опции, чтобы отключить его многословие, поэтому я ищу способ только визуально заставить его замолчать и сохранить открытую оболочку в чистоте для дальнейшего взаимодействия.

Как я могу это сделать?

6 ответов

Решение

Перенаправить вывод в DEVNULL:

import os
import subprocess

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

Фактически это то же самое, что и выполнение этой команды оболочки:

retcode = os.system("echo 'foo' &> /dev/null")

Вот более переносимая версия (просто для удовольствия, в вашем случае она не нужна):

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

Использование subprocess.check_output (Новое в Python 2.7). Это подавит стандартный вывод и вызовет исключение в случае сбоя команды. (На самом деле он возвращает содержимое стандартного вывода, поэтому вы можете использовать его позже в своей программе, если хотите.) Пример:

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

Вы также можете подавить stderr с помощью:

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

Для ранее чем 2.7 используйте

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

Здесь вы можете подавить stderr с помощью

        subprocess._check_call(['espeak', text], stdout=FNULL, stderr=FNULL)

Начиная с Python3 вам больше не нужно открывать devnull и вы можете вызывать subprocess.DEVNULL.

Ваш код будет обновлен как таковой:

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

Если вы используете модуль подпроцесса в Windows (не относится к этому вопросу, но соответствует заголовку) с Python 2.7x, и это ТОЛЬКО ошибки, которые вы хотите подавить (специфичные для этого вопроса), вы можете сделать что-то вроде этого:

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

у вас должна быть возможность протестировать, используя приведенный выше код в вашей системе, но если в вашей таблице arp окажется 127.0.0.2, вы можете просто выбрать ip, с которым не связан ник.

Почему бы не использовать command.getoutput() вместо этого?

import commands

text = "Mario Balotelli" 
output = 'espeak "%s"' % text
print text
a = commands.getoutput(output)
Другие вопросы по тегам