Doppelte Ausgabe beim Umleiten von sys.stdout

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Hallo Leute,
ich habe ein Problem mit dem Umleiten der Standardausgabe.
Ich habe eine Klasse, die mir das aktuelle Datum vor jede Ausgabe setzen soll (Logging).

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import codecs
from locale import getpreferredencoding
import os
from time import strftime
import sys

ENCODING = getpreferredencoding()

class Log(object):
    '''
    Klasse zum Abfangen der print Anweisungen. Umleitung erfolgt wahlweise
    in eine Datei, auf die Kommandozeile oder beides.
    '''
    def __init__(self, logfile = '', rotate = False, cli = True):
        self.stdout = sys.__stdout__
        self.cli = cli
        if logfile:
            self.log = True
            if rotate:
                self.logfile = '%s_%s.log' % (logfile, strftime('%A'))
            else:
                self.logfile = '%s.log' % logfile
        else:
            self.log = False

    def write(self, *text):
        msg = u' '.join(text)
        date = strftime('%W %Y-%m-%d %H:%M:%S')
        if self.cli:
            self.stdout.write('%s %s' % (date, msg.encode(ENCODING)))
        if self.log:
            logfile = self.logfile
            mode = self._check_size(logfile)
            try:
                f = codecs.open(logfile, mode, 'UTF-8')
                f.write('%s %s' % (date, msg))
            finally:
                f.close()

    def _check_size(self, logfile):
        if os.path.isfile(logfile):
            if os.path.getsize(logfile) > 5000:
                return 'w'
            else:
                return 'a'
        else:
            return 'w'

if __name__ == '__main__':
    sys.stdout = Log('app', True, True)
    print u'Logtest öüä'
Wenn ich dieses Skript ausführe, erhalte ich die folgende Ausgabe:

Code: Alles auswählen

04 2007-01-28 08:58:57 Logtest öüä04 2007-01-28 08:58:57
Nun die Frage: Warum wird das Datum doppelt geschrieben ? Und warum wird am Ende ein newline eingefügt ?
Wenn ich in Zeile 33 date nicht schreibe

Code: Alles auswählen

self.stdout.write(msg.encode(ENCODING))
funktioniert alles wie gewünscht. Es wird der String ausgegeben und kein newline angefügt. Genauso sieht es im Logfile aus.

Gruß, Whitie
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Wenn du dir mal ansiehst, was "msg" ist, siehst du, dass einmal "Logtest" und einmal "\n" ausgegeben wird.

Das liegt am "magischen" Verhalten von `print`, das ja mit "," auch Ausgabe ohne Newline unterstützt.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
BlackJack

Whitie hat geschrieben:Nun die Frage: Warum wird das Datum doppelt geschrieben ? Und warum wird am Ende ein newline eingefügt ?
Weil ``print`` am Ende ein Newline ausgibt, und das anscheinend mit einem eigenen Aufruf von `write()`.

Teste mal das hier:

Code: Alles auswählen

    print 1, 2, 3
Da hast Du dann viermal das Datum in der Ausgabe ─ einmal für jede Zahl und einmal für den Zeilenwechsel.
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Danke erstmal,
ich werde mal in Ruhe testen.

Gruß, Whitie
Antworten