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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top