Подавлять вывод в Python-вызовах для исполняемых файлов

У меня есть двоичный файл с именем A, который генерирует вывод при вызове. Если я назову его из оболочки Bash, большая часть вывода будет подавлена ​​A > /dev/null. Весь выход подавляется A &> /dev/null

У меня есть python script с именем B, которому нужно позвонить A. Я хочу иметь возможность генерировать вывод из B, подавляя весь вывод из A.

Из B я пробовал os.system('A'), os.system('A > /dev/null') и os.system('A &> /dev/null'), os.execvp('...') и т.д., но ни один из них не подавляет весь вывод из A.

Я мог бы запустить B &> /dev/null, но это тоже подавляет вывод B, и я не хочу этого.

У кого-нибудь есть предложения?

Ответ 1

Если у вас есть Python 2.4, вы можете использовать модуль подпроцесса:

>>> import subprocess
>>> s = subprocess.Popen(['cowsay', 'hello'], \
      stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
>>> print s
 _______ 
< hello >
 ------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Ответ 2

import os
import subprocess

command = ["executable", "argument_1", "argument_2"]

with open(os.devnull, "w") as fnull:
    result = subprocess.call(command, stdout = fnull, stderr = fnull)

Если у команды нет аргументов, вы можете просто представить ее как простую строку.

Если ваша команда использует функции оболочки, такие как подстановочные знаки, трубы или переменные среды, вам необходимо предоставить всю команду в виде строки, а также указать shell = True. Однако этого следует избегать, поскольку это представляет угрозу безопасности, если содержимое строки не проверено тщательно.

Ответ 3

В Python 3.3 и выше subprocess поддерживает параметр для перенаправления на /dev/null. Чтобы использовать его, при вызове .Popen и друзей укажите stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, как аргументы ключевого слова.

Таким образом, ответ DNS, переписанный для Python 3.3+, становится

import subprocess
command = ["executable", "argument_1", "argument_2"]
result = subprocess.call(command,
                         stdout=subprocess.DEVNULL,
                         stderr=subprocess.DEVNULL)

Из документации:

subprocess.DEVNULL¶

Специальное значение, которое может использоваться как stdin, stdout или stderr аргумент Popen и указывает, что специальный файл os.devnull будет.

Новое в версии 3.3.

Для Python 3.0 - 3.2 вам нужно вручную открыть нулевое устройство с помощью open(os.devnull), как писал DNS.

Ответ 4

Если ваша поисковая система приведет вас к этому старому вопросу (например, мне), имейте в виду, что использование PIPE может привести к взаимоблокировкам. Действительно, поскольку трубы буферизованы, вы можете записать определенное количество байтов в трубе, даже если никто его не читает. Однако размер буфера конечен. И, следовательно, если ваша программа A имеет выход больше, чем буфер, A будет заблокирован при записи, а вызывающая программа B ожидает завершения A. Но нет, в данном конкретном случае... см. Комментарии ниже.

Тем не менее, я рекомендую использовать решение Devin Jeanpierre и DNS.

Ответ 5

Как упоминает os.system(), используйте модуль subprocess, и, если хотите, установите stdout = open (os.devnull, 'w') (и, возможно, одно и то же для stderr), когда вы открываете подпроцесс.

Ответ 6

Я знаю это поздно в игре, но почему бы просто не перенаправить вывод в /dev/null изнутри os.system? Например:.

tgt_file = "./bogus.txt"
os.sytem("d2u '%s' &> /dev/null" % tgt_file)

Это похоже на работу в тех случаях, когда вы не хотите иметь дело с subprocess.STDOUT.

Ответ 7

Я использую:

call(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

где команда - это строка команды + arguments

Для этого вам необходимо импортировать подпроцесс

Ответ 8

Если вам нужно просто захватить STDOUT, не назначает ли это переменной переменной? Например:

megabyte=''
# Create a 1 MiB string of NULL characters.
for i in range(1048576):
    megabyte += '\0'
fh=open('zero.bin','w')
# Write an 8 GiB file.
for i in range(8192):
    print(i)
    # Suppress output of 'write()' by assigning to a variable.
    discard=fh.write(megabyte)
fh.close()

Я создавал большой нуль-заполненный файл на нулевое свободное место на моем жестком диске и обнаружил, что каждый вызов handle.write(string) выплескивает количество записанных байтов. Присвоение его к vairable подавляло этот вывод.

Ответ 9

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

Например, запуск звукового файла с помощью aplay:

import os

def PlaySound(filename):
    command = 'bash -c "aplay %s &> /dev/null &"' % (filename)
    os.system(command)

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