Seite 1 von 1

Doppelte Ausgabe beim Umleiten von sys.stdout

Verfasst: Sonntag 28. Januar 2007, 09:15
von Whitie
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

Verfasst: Sonntag 28. Januar 2007, 10:06
von birkenfeld
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.

Re: Doppelte Ausgabe beim Umleiten von sys.stdout

Verfasst: Sonntag 28. Januar 2007, 10:13
von 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.

Verfasst: Sonntag 28. Januar 2007, 10:21
von Whitie
Danke erstmal,
ich werde mal in Ruhe testen.

Gruß, Whitie