Как вы подклассифицируете тип файла в Python?
Я пытаюсь подклассифицировать встроенный класс file
в Python, чтобы добавить дополнительные функции в stdin
и stdout
. Вот код, который у меня есть до сих пор:
class TeeWithTimestamp(file):
"""
Class used to tee the output of a stream (such as stdout or stderr) into
another stream, and to add a timestamp to each message printed.
"""
def __init__(self, file1, file2):
"""Initializes the TeeWithTimestamp"""
self.file1 = file1
self.file2 = file2
self.at_start_of_line = True
def write(self, text):
"""Writes text to both files, prefixed with a timestamp"""
if len(text):
# Add timestamp if at the start of a line; also add [STDERR]
# for stderr
if self.at_start_of_line:
now = datetime.datetime.now()
prefix = now.strftime('[%H:%M:%S] ')
if self.file1 == sys.__stderr__:
prefix += '[STDERR] '
text = prefix + text
self.file1.write(text)
self.file2.write(text)
self.at_start_of_line = (text[-1] == '\n')
Цель состоит в том, чтобы добавить временную метку к началу каждого сообщения и записать все в файл журнала. Однако проблема, с которой я сталкиваюсь, заключается в том, что если я это сделаю:
# log_file has already been opened
sys.stdout = TeeWithTimestamp(sys.stdout, log_file)
Тогда, когда я пытаюсь сделать print 'foo'
, я получаю a ValueError: I/O operation on closed file
. Я не могу с полным основанием называть file.__init__()
в моем __init__()
, так как я не хочу открывать новый файл, и я не могу назначить self.closed = False
, так как это атрибут только для чтения.
Как я могу изменить это, чтобы я мог сделать print 'foo'
, и чтобы он поддерживал все стандартные атрибуты и методы file
?
Ответы
Ответ 1
Вызов file.__init__
вполне возможен (например, в '/dev/null'), но не используется, потому что ваше попытка переопределения write
не "принимает" для целей операторов print
- последний внутренне вызывает реальную file.write
, когда видит, что sys.stdout
является фактическим экземпляром file
(и, наследуя, вы сделали это).
print
действительно не нужен какой-либо другой метод, кроме write
, поэтому использование класса наследуется от object
вместо file
.
Если вам нужны другие методы файлов (т.е. print
- это еще не все, что вы делаете), вам лучше всего их реализовать.
Ответ 2
Вы также можете избежать использования super
:
class SuperFile(file):
def __init__(self, *args, **kwargs):
file.__init__(self, *args, **kwargs)
Вы сможете написать с ним.