Подавление вывода вызова модуля вне библиотеки
У меня раздражает проблема при использовании библиотеки машинного обучения PyML. PyML использует libsvm для обучения классификатора SVM. Проблема в том, что libsvm выводит некоторый текст на стандартный вывод. Но поскольку это за пределами Python, я не могу его перехватить. Я попытался использовать методы, описанные в проблеме. Выключить стандартный вывод функции в Python, не удаляя sys.stdout и восстанавливая каждый вызов функции, но ни одна из них не помогла.
Есть ли способ, как это сделать. Модификация PyML не вариант.
3 ответа
Открыто /dev/null
для написания используйте os.dup()
скопировать стандартный вывод и использовать os.dup2()
скопировать ваш открытый /dev/null
на стандартный вывод использование os.dup2()
скопировать скопированный стандартный вывод обратно в настоящий стандартный вывод после.
devnull = open('/dev/null', 'w')
oldstdout_fno = os.dup(sys.stdout.fileno())
os.dup2(devnull.fileno(), 1)
makesomenoise()
os.dup2(oldstdout_fno, 1)
Дейв Смит дал прекрасный ответ на этот вопрос в своем блоге. По сути, это красиво оборачивает ответ Игнасио:
def suppress_stdout():
with open(os.devnull, "w") as devnull:
old_stdout = sys.stdout
sys.stdout = devnull
try:
yield
finally:
sys.stdout = old_stdout
Теперь вы можете окружить любую функцию, которая искажает нежелательный шум, в stdout следующим образом:
print "You can see this"
with suppress_stdout():
print "You cannot see this"
print "And you can see this again"
Для Python 3 вы можете использовать:
from contextlib import contextmanager
import os
import sys
@contextmanager
def suppress_stdout():
with open(os.devnull, "w") as devnull:
old_stdout = sys.stdout
sys.stdout = devnull
try:
yield
finally:
sys.stdout = old_stdout
У меня была аналогичная проблема с инициализацией portaudio/PyAudio. Я начал с ответа Рейда, который сработал. Хотя вместо этого мне нужно было перенаправить stderr. Итак, вот обновленная кроссплатформенная версия, которая перенаправляет оба:
import sys, os
# hide diagnostic output
with open(os.devnull, 'w') as devnull:
# suppress stdout
orig_stdout_fno = os.dup(sys.stdout.fileno())
os.dup2(devnull.fileno(), 1)
# suppress stderr
orig_stderr_fno = os.dup(sys.stderr.fileno())
os.dup2(devnull.fileno(), 2)
print('*** stdout should be hidden! ****')
print('*** stderr should be too! ****',
file=sys.stderr)
os.dup2(orig_stdout_fno, 1) # restore stdout
os.dup2(orig_stderr_fno, 2) # restore stderr
print('done.')
Должно быть легко закомментировать ненужную часть.
У меня была такая же проблема, и я исправил это так:
from cStringIO import StringIO
def wrapped_svm_predict(*args):
"""Run :func:`svm_predict` with no *stdout* output."""
so, sys.stdout = sys.stdout, StringIO()
ret = svm_predict(*args)
sys.stdout = so
return ret