logging erzeugt keine UTF-8 Files

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
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Grüße

Habe mir eine Logger Klasse(die getrennte Dateien erzeugen kann) geschustert.
Aber zu meiem Problem: Die erzeugten Dateien sind immer im ANSI Format codiert. Geht es überhaupt, dass der logger UTF-8 Dateien erzeugt?

Code: Alles auswählen

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

import os
import logging
from datetime import datetime


class Logger(object):
    def __init__(self, filefullpath):
        logger_name = '%s' % datetime.now()
        print logger_name

        directoryname, filename = os.path.split(filefullpath)
        print directoryname
        print filename

        if not os.path.exists(directoryname):
            os.makedirs(directoryname)

        self.logger = logging.getLogger(logger_name)
        formatter = logging.Formatter('%(asctime)-15s: %(message)s')
        fileHandler = logging.FileHandler(filefullpath, mode='w', encoding='utf-8')
        fileHandler.setFormatter(formatter)
        self.logger.setLevel(logging.INFO)
        self.logger.addHandler(fileHandler)

    def log(self, string):
        self.logger.info('%s' % string.decode('utf-8'))

def main():
    filefullpath_a = datetime.now().strftime('test/%Y%m%d_%H%M%S_file_a.log')
    filefullpath_b = datetime.now().strftime('test/%Y%m%d_%H%M%S_file_b.log')

    log_a = Logger(filefullpath_a)
    log_b = Logger(filefullpath_b)

    log_a.log('Started 1')
    log_a.log('jdfhshdfjshkfj 1')
    log_a.log('Finished 1')

    log_b.log('Started 2')
    log_b.log('jdfhshdfjshkfj 2')
    log_b.log('Finished 2')


if __name__ == '__main__':
    main()
Zuletzt geändert von harryberlin am Dienstag 8. November 2016, 19:01, insgesamt 1-mal geändert.
empty Sig
BlackJack

@harryberlin: Wie hast Du das denn überprüft? Bei dem gezeigten Quelltext wird ja nur ASCII in die Datei geschrieben, das ist sowohl ”ANSI” als auch UTF-8, und noch ein Haufen anderer Kodierungen die ASCII als Untermenge haben.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

wenn ich z.B. unter windows im notepad die log-datei öffne und dann "speichern unter", wird mir bei der codierung "ANSI" angezeigt.

Bild
empty Sig
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Es gibt kein ANSI Encoding bzw. ist der Begriff nicht klar definiert. Was allerdings klar ist dass alles was du loggst in ASCII repräsentierbar ist. ASCII ist ein Subset von vielen Encodings, unter anderem UTF-8. Du kannst also gar nicht wissen ob es UTF-8 ist oder ein anderes Encoding.

Von dem eigentlichen Problem abgesehen ist dass was du da machst mehr als fragwürdig. Zum einen entspricht dass nicht dem wie man Logging benutzen sollte, zum anderen schränkst du die Fähigkeiten von logging extrem und vollkommen unnötig auf ein fragwürdiges Minimum ein. Den Logger nach der aktuellen Zeit zu benennen ist darüberhinaus einfach nur absurd.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ich möchte gleichzeitig in zwei oder sogar noch mehr dateien unterschiedliche texte loggen können.
da kam mir die benennung nach zeit als einfachste lösung. weil diese eigentlich nie gleich ist. zur not muss eben noch eine ms sleep rein.
empty Sig
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

das schaut dann z.B. so aus:

Bild
Zuletzt geändert von harryberlin am Dienstag 8. November 2016, 19:20, insgesamt 1-mal geändert.
empty Sig
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@harryberlin: wenn Du unterschiedliche Texte loggen möchtest, dann nenn sie doch nach dem, was sie unterscheiden. So funktioniert aber logging nicht. Üblicherweise will man ja alles in einer Datei haben, und sortiert bei Bedarf nach Kategorien. Es ist nicht möglich, immer das richtige Encoding zu erraten. Und das Programm, dessen Screenshot Du da zeigst, ist auch noch sehr primitiv, nicht nur, was das Erkennen von Encodings angeht.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

hab grad im hexeditor geschaut. die datei hat keine UTF-8 BOM am anfang.
sinnvollerweise möchte ich getrennte dateien.
empty Sig
BlackJack

@harryberlin: Natürlich hat die Datei kein BOM, warum sollte sie? Bei UTF-8 gibt es keine Byteorder, also braucht man auch kein BOM.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

laut wikipedia aber schon. https://de.wikipedia.org/wiki/Byte_Order_Mark

kann ich das denn irgendwie rein bringen?
empty Sig
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

habe jetzt ein workaround erstellt. es wird die datei erstellt und die bytes werden geschrieben. mit dem logger öffne ich sie dann und logge hinzu.

Code: Alles auswählen

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

import os
import logging
from datetime import datetime


class Logger(object):
    def __init__(self, filefullpath):
        logger_name = '%s' % datetime.now()
        print logger_name

        directoryname, filename = os.path.split(filefullpath)
        print directoryname
        print filename

        if not os.path.exists(directoryname):
            os.makedirs(directoryname)
        
        # write UTF-8 BOM
        with open(filefullpath, 'wb') as f:
            f.write(bytearray([0xEF, 0xBB, 0xBF]))

        self.logger = logging.getLogger(logger_name)
        formatter = logging.Formatter('%(asctime)-15s: %(message)s')
        fileHandler = logging.FileHandler(filefullpath, mode='a', encoding='utf-8')
        fileHandler.setFormatter(formatter)
        self.logger.setLevel(logging.INFO)
        self.logger.addHandler(fileHandler)

    def log(self, string):
        self.logger.info('%s' % string.decode('utf-8'))


def main():
    filefullpath_a = os.path.join('test', 'file_a.log')
    filefullpath_b = os.path.join('test', 'file_b.log')

    log_a = Logger(filefullpath_a)
    log_b = Logger(filefullpath_b)

    log_a.log('Started 1')
    log_a.log('jdfhshdfjshkfj 1')
    log_a.log('Finished 1')

    log_b.log('Started 2')
    log_b.log('jdfhshdfjshkfj 2')
    log_b.log('Finished 2')


if __name__ == '__main__':
    main()
Zuletzt geändert von harryberlin am Dienstag 8. November 2016, 22:18, insgesamt 3-mal geändert.
empty Sig
BlackJack

@harryberlin: Natürlich kann man den BOM auch in UTF8 kodieren, aber er macht in UTF8 nicht wirklich Sinn weil es dort das Problem was damit gelöst werden soll gar nicht gibt. Warum willst Du den Unsinn da drin haben? Das macht am Ende nur Ärger wenn Du irgendwelche Software verwendest die damit nichts anfangen kann und/oder es nicht heraus filtert. Das bei UTF8 als Kodierungshinweis zu verwenden ist halbgar, denn letztendlich gilt bei Kodierungen immer das man nicht raten sondern wissen sollte. Aber hey, es geht ja wahrscheinlich um Windows. Mach was Du willst. :-)
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

solang ich das logfile in linux öffne, passt es auch.
wenn ich unter windows das log öffne werden diverse zeichen falsch dargestellt. z.B. "°"
empty Sig
BlackJack

@harryberlin: Ich würde dann ja eher die Software wechseln statt an den Daten rumzufummeln. Notepad ist kein vernünftiger Texteditor.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@harryberlin: Du öffnest die Datei halt unter Windows falsch (mit dem falschen Editor). Die Logger-Klasse ist nicht wirklich eine Klasse, da sie nur einen Logger konfiguriert, das wäre besser eine Funktion. Eine Variable filefullpath für einen relative Pfadangabe zu nehmen, ist irreführend. strftime für einen konstanten String unsinnig.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@blackjack
in wordpad besteht das selbe problem. mit dem falsch dargestellten zeichen.

@sirius3
ja du hast recht, für das beispiel hier, ist der relative pfad nicht wirklich ein fullpath.
habs schon auf os.path.join() angepasst. bin dann selbst drauf gekommen, dass es schwachsinn war.
anders als mit der klasse kann ich doch sonst keine instanzen erzeugen.
empty Sig
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@harryberlin: wir reden von Editoren und Du kommst mit wordpad? Die Instanz, die Du benutzen solltest, ist vom Typ »logging.Logger«.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

was sollte ich an einem logfile denn editieren wollen?
vllt. verstehe ich es auch falsch. ein log ist eine mitschrift. wenn ich nachträglich was dran editiere, dann kann ich das machen, aber hat keine auswirkung.
für python nutze ich pycharm.
empty Sig
BlackJack

@harryberlin: Auch wenn Du eine Textdatei nur anschauen willst, öffnest Du sie in einem Texteditor. Reine Anzeigeprogramme gibt es in dem Bereich ja eher nicht. Deswegen reden wir von Texteditoren. Notepad ist kein guter Texteditor, und Wordpad ist gar keiner. Das ist eine Textverarbeitung in die Du den Text halt importieren kannst. Beide Programme sind uralt und stammen noch aus Zeiten bevor UTF-8 breitere Verwendung fand.

Ein guter Texteditor zum Programmieren sollte UTF-8 auch ohne BOM erraten, oder standardmässig darauf eingestellt werden können. Und dann kann man den auch zum betrachten von Protokolldateien verwenden.

Wenn Du PyCharm sowieso offen hast, könntest Du das auch zum betrachten der Protokolldateien verwenden.
Antworten