Я хочу подавить весь вывод терминала, созданный функцией, которая запускает исполняемые файлы.Как можно отключить вывод терминалов, выполняемых функциями Python, в общем виде?
Я попытался подавить вывод функции Python с помощью диспетчера контекста, который временно переопределяет stdout и stderr каждый раз, когда вызывается функция. Это подавляет вывод терминала, вызванный print
вызовами в функции, но, похоже, не работает, когда функция вызывает исполняемые файлы, которые производят вывод терминала.
Итак, как можно скрыть вывод исполняемых файлов, вызываемых функциями Python?
Мой код ниже. Я включил пример функции, которая вызывает ls
, чтобы попытаться проиллюстрировать тип вывода терминала, который я хочу подавить (хотя функция, с которой я имею дело, отличается).
#!/usr/bin/env python
import os
import subprocess
import sys
def main():
print("hello")
with silence():
print("there")
print("world")
with silence():
engage_command(command = "ls")
class silence(object):
def __init__(
self,
stdout = None,
stderr = None
):
if stdout == None and stderr == None:
devnull = open(os.devnull, "w")
stdout = devnull
stderr = devnull
self._stdout = stdout or sys.stdout
self._stderr = stderr or sys.stderr
def __enter__(
self
):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.old_stdout.flush()
self.old_stderr.flush()
sys.stdout = self._stdout
sys.stderr = self._stderr
def __exit__(
self,
exc_type,
exc_value,
traceback
):
self._stdout.flush()
self._stderr.flush()
sys.stdout = self.old_stdout
sys.stderr = self.old_stderr
def engage_command(
command = None
):
process = subprocess.Popen(
[command],
shell = True,
executable = "/bin/bash")
process.wait()
output, errors = process.communicate()
return output
if __name__ == "__main__":
main()
В моем конкретном случае, я пытаюсь запустить следующую функцию (вместо ls
функции выше):
with propyte.silence():
stream = pyaudio.PyAudio().open(
format = pyaudio.PyAudio().get_format_from_width(1),
channels = 1,
rate = bitrate,
output = True
)
При запуске, это производит вывод наподобие следующего:
ALSA lib pcm_dsnoop.c:606:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:1029:(snd_pcm_dmix_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for 4294967295, skipping unlock
Я хочу подавить этот выход.
EDIT: тестирование a solution предоставленного @Matthias
#!/usr/bin/env python
import contextlib
import os
import subprocess
import sys
def main():
print("hello")
with silence():
print("there")
print("world")
with silence():
engage_command(command = "ls")
@contextlib.contextmanager
def silence():
devnull = os.open(os.devnull, os.O_WRONLY)
old_stderr = os.dup(2)
sys.stderr.flush()
os.dup2(devnull, 2)
os.close(devnull)
try:
yield
finally:
os.dup2(old_stderr, 2)
os.close(old_stderr)
def engage_command(
command = None
):
process = subprocess.Popen(
[command],
shell = True,
executable = "/bin/bash")
process.wait()
output, errors = process.communicate()
return output
if __name__ == "__main__":
main()
Я не был успешным в подавлении терминального выхода из print
или ls
, и я не знаю, почему.
Большое спасибо за подробное решение. Я буду исследовать модуль sounddevice, как было предложено, и рассмотрит его решение для отключения PortAudio. Для чистого общего подхода к отключению терминала полностью (будь то для вывода Python или исполняемых файлов, запущенных Python), которые вы предложили, мне не удалось заставить его подавить вывод терминала. Я поместил свой код в редактирование вопроса. Есть ли у вас какое-либо представление о том, как изменить его так, чтобы вывод терминала 'print' и' ls' был подавлен? – d3pd
А, вот и все. Нужно было обрабатывать stdout. Еще раз спасибо за четкое и подробное решение. – d3pd