Подавление вывода вызова модуля вне библиотеки

У меня раздражает проблема при использовании библиотеки машинного обучения 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
Другие вопросы по тегам