#python
Есть python скрипт: import sys sys.stdout = open('my_log.log', 'w') print 'test' Он пишет весь стандартный вывод в файл. Вопрос: как мне и писать в файл, и одновременно выводить на консоль?
Ответы
Ответ 1
Как наколеночное решение, буквально выполняющее задачу, озвученную в вопросе: можно создать класс, который принимает два файловых объекта, и при записи в объект данного класса выполнять запись в оба файловых объекта. import sys class DoubleWrite: def __init__(self, file1, file2): self.file1 = file1 self.file2 = file2 def write(self, s): self.file1.write(s) self.file2.write(s) def flush(self): self.file1.flush() self.file2.flush() logfile = open('my_log.log', 'w') sys.stdout = DoubleWrite(sys.stdout, logfile) print "test" В целом, для логирования рекомендуется использовать уже существующие решения, в частности модуль logging. Обновление. Для корректного перенаправления и последующего восстановления sys.stdout в Python 3 лучше использовать менеджер контекста contextlib.redirect_stdout. В стандартной библиотеке Python 2 такого менеджера контекста, к сожалению, нет. Пример использования (для Python 3): import sys from contextlib import redirect_stdout class DoubleWrite: ... with open('my_log.log', 'w') as logfile: with redirect_stdout(DoubleWrite(sys.stdout, logfile)): print('test') После выхода из блока with redirect_stdout(...) значение sys.stdout восстановится.Ответ 2
Используя модуль logging: def get_logger(name=__file__, file='log.txt', encoding='utf-8'): import logging log = logging.getLogger(name) log.setLevel(logging.DEBUG) # Будут строки вида: "[2017-08-23 09:54:55,356] main.py:34 DEBUG foo" # formatter = logging.Formatter('[%(asctime)s] %(filename)s:%(lineno)d %(levelname)-8s %(message)s') formatter = logging.Formatter('%(message)s') # В файл from logging import FileHandler fh = FileHandler(file, encoding=encoding) fh.setFormatter(formatter) log.addHandler(fh) # В stdout import sys sh = logging.StreamHandler(stream=sys.stdout) sh.setFormatter(formatter) log.addHandler(sh) return log log = get_logger() log.debug('foo') log.debug('bar') Можно настроить формат вывода, указав в Formatter '[%(asctime)s] %(filename)s:%(lineno)d %(levelname)-8s %(message)s' и получать такие строки: [2017-08-23 09:54:55,356] main.py:34 DEBUG foo [2017-08-23 09:54:55,356] main.py:34 DEBUG barОтвет 3
Проксирует вызов на все содержимое списка import sys class CallList(list): def __getattr__(self, attr): def func(*args, **kwargs): for obj in self: getattr(obj, attr)(*args,**kwargs) return func cl = CallList([open('file.test', 'w'), sys.stdout]) cl.write("0xDEFACE") cl.flush()Ответ 4
def echo(file): with open(file, 'w') as log: while True: text = yield log.write(text + '\n') print(text) e = echo('log.txt') next(e) e.send('123') e.send('456')
Комментариев нет:
Отправить комментарий