Come si fa a sottoclasse il tipo di file in Python?
Domanda
Sto cercando di creare una sottoclasse della classe file
incorporato in Python per aggiungere alcune funzioni extra per stdin
e stdout
. Ecco il codice che ho finora:
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')
Lo scopo è quello di aggiungere un timestamp all'inizio di ogni messaggio, e per registrare tutto ciò che un file di log. Tuttavia, il problema che ho incontrato è che se faccio questo:
# log_file has already been opened
sys.stdout = TeeWithTimestamp(sys.stdout, log_file)
Poi, quando provo a fare print 'foo'
, ho un ValueError: I/O operation on closed file
. Non posso chiamare per significato file.__init__()
nel mio __init__()
, dal momento che non voglio aprire un nuovo file, e non posso assegnare self.closed = False
sia, dal momento che è un attributo di sola lettura.
Come posso modificare questo in modo che io possa fare print 'foo'
, e in modo che supporta tutti gli attributi file
standard e metodi?
Soluzione
Calling file.__init__
è abbastanza fattibile (ad esempio, su '/ dev / null'), ma nessuna vera utilizzo perché il tentativo di forzatura dei write
non "prende" ai fini delle dichiarazioni print
- quest'ultimo chiama internamente il vero file.write
quando si vede che sys.stdout
è un'istanza effettiva di file
(e da voi ereditando hai fatto così).
print
non ha veramente bisogno qualsiasi altro metodo, tranne write
, in modo da rendere la vostra eredita dalla classe object
invece di file
funzionerà.
Se avete bisogno di altri metodi di file (vale a dire, print
non è tutto si sta facendo), si sta meglio consigliato di implementare da soli.
Altri suggerimenti
Si può anche evitare di usare super
:
class SuperFile(file):
def __init__(self, *args, **kwargs):
file.__init__(self, *args, **kwargs)
Sarete in grado di scrivere con esso.