Подавлять вывод в 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, а также процесс, который вы выполняете, предоставляя небольшие накладные расходы.