Как захватить вывод stdout из вызова функции Python?
Я использую библиотеку Python, которая что-то делает для объекта
do_something(my_object)
и изменяет его. При этом он печатает некоторые статистические данные для stdout, и я хотел бы получить доступ к этой информации. Правильным решением было бы изменить do_something()
, чтобы вернуть соответствующую информацию,
out = do_something(my_object)
но до того, как разработчики do_something()
получат эту проблему, пройдет некоторое время. В качестве обходного пути я подумал о том, чтобы разбор всех do_something()
записывался в stdout.
Как я могу записать вывод stdout между двумя точками в коде, например,
start_capturing()
do_something(my_object)
out = end_capturing()
?
Ответы
Ответ 1
Попробуйте этот контекстный менеджер:
# import StringIO for Python 2 or 3
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import sys
class Capturing(list):
def __enter__(self):
self._stdout = sys.stdout
sys.stdout = self._stringio = StringIO()
return self
def __exit__(self, *args):
self.extend(self._stringio.getvalue().splitlines())
del self._stringio # free up some memory
sys.stdout = self._stdout
Использование:
with Capturing() as output:
do_something(my_object)
output
теперь является списком, содержащим строки, напечатанные вызовом функции.
Расширенное использование:
Что может быть неочевидным, так это то, что это можно сделать несколько раз и результаты объединены:
with Capturing() as output:
print 'hello world'
print 'displays on screen'
with Capturing(output) as output: # note the constructor argument
print 'hello world2'
print 'done'
print 'output:', output
Выход:
displays on screen
done
output: ['hello world', 'hello world2']
Обновление: они добавили redirect_stdout()
в contextlib
в Python 3.4 (вместе с redirect_stderr()
). Таким образом, вы можете использовать io.StringIO
этого, чтобы достичь аналогичного результата (хотя, возможно, удобнее Capturing
как список, так и контекстный менеджер).
Ответ 2
В python >= 3.4, contextlib содержит redirect_stdout
декоратор. Его можно использовать для ответа на ваш вопрос следующим образом:
import io
from contextlib import redirect_stdout
f = io.StringIO()
with redirect_stdout(f):
do_something(my_object)
out = f.getvalue()
Из документов:
Контекстный менеджер для временного перенаправления sys.stdout в другой файл или файл-подобный объект.
Этот инструмент добавляет гибкость существующим функциям или классам, выход жестко подключен к стандартным выводам.
Например, вывод справки() обычно отправляется на sys.stdout. Вы может захватить этот вывод в строке путем перенаправления вывода на Объект io.StringIO:
f = io.StringIO()
with redirect_stdout(f):
help(pow)
s = f.getvalue()
Чтобы отправить вывод справки() в файл на диске, перенаправьте вывод на обычный файл:
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
Чтобы отправить вывод справки() в sys.stderr:
with redirect_stdout(sys.stderr):
help(pow)
Обратите внимание, что глобальный побочный эффект на sys.stdout означает, что этот контекст менеджер не подходит для использования в библиотечном коде и в большинстве потоков Приложения. Он также не влияет на вывод подпроцессов. Тем не менее, это по-прежнему полезный подход для многих сценариев использования.
Этот менеджер контекста является реентерабельным.
Ответ 3
Взгляните на эту ссылку о чтении и записи файлов в Python. Это должно дать вам понять, как писать вещи в файл в Различные пути.