2017-01-08 6 views
2

Мне нужно сохранить в файл те же журналы, что и в консоли, поэтому я редактирую sys.stdout. (Использование кода от Redirect stdout to a file in Python?)Python: Редактирование текста на персональном stdout - удвоенный текст

Но проблема показывает, когда я пытался редактировать текст в функции записи, добавляя что-то перед ним. В результате этот «[stack]» добавляет до и после текстовой переменной.

import sys 

class Logger(object): 
    def __init__(self): 
     self.terminal = sys.stdout 
     self.file = open("log.txt", "a") 
    def flush(self): 
     self.terminal.flush() 
     self.file.flush() 
    def write(self, text): 
     self.terminal.write("[stack]" + text) 
     self.file.write(text) 
     self.flush(); 

sys.stdout = Logger() 

print "Test log" 
print "Another test log" 

Результат:

[stack]Test log[stack] 
[stack]Another test log[stack] 
+0

'print 'Журнал испытаний' 'выполняется как' write ("Test log") 'и' write ("\ n") '- поэтому вы получаете' write ("[stack]" + "Test log") 'и' write ("[stack]" + "\ n") '. Попробуйте с запятой 'print" Test "," log "' и вы получите еще больше '[stack]' - '[stack] Test [stack] [stack] log [stack]' :) – furas

ответ

4

Я почесал голову на этом, пока я не понял, я должен просто запустить его через отладчик. Причина, по которой это происходит, заключается в том, что при использовании print он попытается написать как текст текста, так и сконфигурированный end, который по умолчанию является символом новой строки.

Каждый print утверждение, следовательно, приводит в двух отдельных вызовов на Logger.write, один из которых представляет собой (например) Test Log, а второй, который является \n. Это приводит к выводу [stack] Test Log[stack]\n.

Вот исправленный реализация:

import sys 


class Logger(object): 
    def __init__(self, stream, default_sep=' ', default_end='\n'): 
     self.terminal = stream 
     self.default_sep = default_sep 
     self.default_end = default_end 
     self.continuing_same_print = False 
     self.file = open("log.txt", "a") 

    def flush(self): 
     self.terminal.flush() 
     self.file.flush() 

    def write(self, text): 
     if text is self.default_end: 
      self.continuing_same_print = False 
     elif text is self.default_sep: 
      self.continuing_same_print = True 

     new_text = text 
     if text in {self.default_sep, self.default_end}: 
      pass 
     elif self.continuing_same_print: 
      pass 
     else: 
      new_text = '[stack]' + new_text 

     self.terminal.write(new_text) 
     self.file.write(text) 
     self.flush() 


sys.stdout = Logger(sys.stdout) 

print("Test", "log") 
print("Another test log") 
print() 

Выход

[stack]Test log 
[stack]Another test log 

Редактировать

Обновлено реализация для поддержки нескольких объектов печатаются в печатном заявлении.

+0

попробуйте с 'print (" Test "," log ")', и вы получаете '[stack] Test [stack] [stack] log' :) Это все еще нуждается в некоторой работе. – furas

+0

@furas Хорошо, я на нем. – Tagc

+0

так ... Удачи. :) – furas

0

Если вы используете Python3, вы можете перегрузить встроенный print для настройки вывода. Ниже код дает ожидаемый результат:

import sys 
import builtins 

class Logger(object): 
    def __init__(self): 
     self.terminal = sys.stdout 
     self.file = open("log.txt", "a") 
    def flush(self): 
     self.terminal.flush() 
     self.file.flush() 
    def write(self, text): 
     self.terminal.write(text) 
     self.file.write(text) 
     self.flush(); 

def myprint(string): 
    builtins.print("%s%s" % ("[stack]", string)) 

print = myprint 

sys.stdout = Logger() 

 Смежные вопросы

  • Нет связанных вопросов^_^