2010-11-14 2 views
4

У меня есть неприятная проблема при использовании библиотеки машинного обучения PyML. PyML использует libsvm для обучения классификатора SVM. Проблема в том, что libsvm выводит текст на стандартный вывод. Но поскольку это за пределами Python, я не могу его перехватить. Я пробовал использовать методы, описанные в задаче Silence the stdout of a function in Python without trashing sys.stdout and restoring each function call, но ни один из них не помогает.Подавление вывода вызова модуля вне библиотеки

Есть ли способ, как это сделать. Изменение PyML не является вариантом.

+0

вы проверить это, может быть, это написать в sys.stderr и не sys.stdout !!! – mouad

+0

related: [Перенаправить stdout в файл в Python?] (Http://stackoverflow.com/a/22434262/4279) - в этом случае файл 'os.devnull'. – jfs

ответ

8

Открыть /dev/null для записи, использовать os.dup(), чтобы скопировать stdout и использовать os.dup2(), чтобы скопировать ваш открытый /dev/null на стандартный вывод. Используйте os.dup2(), чтобы скопировать ваш скопированный stdout обратно в реальный stdout после.

devnull = open('/dev/null', 'w') 
oldstdout_fno = os.dup(sys.stdout.fileno()) 
os.dup2(devnull.fileno(), 1) 
makesomenoise() 
os.dup2(oldstdout_fno, 1) 
+0

'oldstdout = os.dup (sys.stdout)' throws theerrorerror 'требуется целое число' – Rok

+3

выяснить, sys.stdout.fileno() и devnull.fileno() необходимы, и это работает после этого, спасибо! ! – Rok

+0

Это работало безупречно для меня. Благодаря! – Will

0

У меня была такая же проблема, и установил ее так:

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 
+0

Это будет работать, если svm_predict - это вывод, полученный из python, но не в том случае, если он поступает из разделяемой библиотеки, которая вызывает вызовы python, и я считаю, о чем спрашивал OP. –

+0

Для меня это работало с использованием привязок Python * libsvm *. Думаю, для PyML ситуация похожа. Stdout - это свойство процесса, то есть моя упаковка (а также решение Ignacio) отлично работает, пока внешние функции не используются через подпроцессы. Это не сработает, если кто-то откроет '/ dev/stdout' для записи вывода. –

+0

Это именно то, что делают большинство разделяемых библиотек, поэтому это решение не будет работать для большинства людей. Вышеупомянутое решение будет ближе к тому, что требуется запрашивающему. – kamelkev

0

Дэйв Смит дал замечательный ответ, что на его blog. В основном, это оборачивает ответ Игнасио красиво:

def suppress_stdout(): 
    with open(os.devnull, "w") as devnull: 
     old_stdout = sys.stdout 
     sys.stdout = devnull 
     try: 
      yield 
     finally: 
      sys.stdout = old_stdout 

Теперь вы можете окружить любую функцию, которая искажает нежелательный шум в стандартный вывод, как это:

print "You can see this" 
with suppress_stdout(): 
    print "You cannot see this" 
print "And you can see this again"