2009-07-04 6 views
13

Ich versuche, die integrierte file Klasse in Python zu untergliedern, um einige zusätzliche Funktionen zu stdin und stdout hinzuzufügen. Hier ist der Code Ich habe bisher:Wie unterklassieren Sie den Dateityp in Python?

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') 

Der Zweck ist, einen Zeitstempel an den Anfang jeder Nachricht hinzuzufügen, und alles in eine Protokolldatei zu protokollieren. Allerdings ist das Problem, das ich in laufen, wenn ich dies tun:

# log_file has already been opened 
sys.stdout = TeeWithTimestamp(sys.stdout, log_file) 

Dann, wenn ich versuche print 'foo' zu tun, ich ein ValueError: I/O operation on closed file bekommen. Ich kann nicht sinnvoll file.__init__() in meinem __init__() aufrufen, da ich keine neue Datei öffnen möchte, und ich kann self.closed = False auch nicht zuweisen, da es ein schreibgeschütztes Attribut ist.

Wie kann ich dies ändern, so dass ich print 'foo' tun kann, und so dass es alle Standard file Attribute und Methoden unterstützt?

Antwort

12

file.__init__ Aufruf ist durchaus möglich (zB auf ‚/ dev/null‘), aber keine wirkliche Verwendung, weil Ihr versucht, außer Kraft gesetzt write nicht „nehmen“ für die Zwecke der print Aussagen - letztere ruft intern die reale file.write wenn es sieht, dass sys.stdout eine tatsächliche Instanz von file ist (und durch Erben haben Sie es so gemacht).

print braucht nicht wirklich eine andere Methode außer write, so dass Ihre Klasse erbt von object statt file werden machen arbeiten.

Wenn Sie andere Dateimethoden benötigen (d. H. print ist nicht alles, was Sie tun), sollten Sie sie am besten selbst implementieren.

+0

Ich bin mir nicht sicher, welche Funktion ich brauche, aber ich möchte sicherlich einige der am häufigsten verwendeten implementiert haben. Ich nehme an, ich beiße nur in den sauren Apfel und setze die ein, die ich brauche, und leite von Objekt statt von Datei ab. –

+0

Welche Methoden außer Schreiben werden normalerweise auf sys.stdout verwendet? Vielleicht Schreibmaschinen, schließen, flush - alles ziemlich einfach (und Sie müssten sie sowieso selbst implementieren - wie könnte der Dateityp wissen, um Ihre Dateien sowieso zu schließen oder zu leeren?! -) –

+0

Ja, Sie haben Recht Wenn ich über die Dateischnittstelle blicke, brauche ich nur noch write, writelines, close und flush. Alles andere sollte niemals auf sys.stdout oder sys.stderr aufgerufen werden. –

2

Sie können auch vermeiden super mit:

class SuperFile(file): 

    def __init__(self, *args, **kwargs): 
     file.__init__(self, *args, **kwargs) 

Sie werden in der Lage, mit ihm zu schreiben.

+0

Entschuldigung, ich hatte einen Fehler, das funktioniert ganz gut. –