Lesen von Unicode-Dateidaten mit BOM-Zeichen in Python

Ich lese eine Reihe von Quellcode-Dateien mit Python und läuft in einen Unicode-BOM-Fehler. Hier ist mein Code:

bytes = min(32, os.path.getsize(filename)) raw = open(filename, 'rb').read(bytes) result = chardet.detect(raw) encoding = result['encoding'] infile = open(filename, mode, encoding=encoding) data = infile.read() infile.close() print(data) 

Wie Sie sehen können, chardet ich die Codierung mit chardet , dann lese ich die Datei im Gedächtnis und versuche es zu drucken. Die Druckanweisung schlägt auf Unicode-Dateien fehl, die eine Stückliste mit dem Fehler enthalten:

UnicodeEncodeError: 'charmap' Codec kann Zeichen in Position 0-2 nicht kodieren:
Zeichenkarten zu <undefined>

Ich vermute, es ist der Versuch, die Stückliste mit dem Standard-Zeichensatz zu dekodieren und es ist fehlgeschlagen. Wie entferne ich die Stückliste aus dem String, um das zu verhindern?

5 Solutions collect form web for “Lesen von Unicode-Dateidaten mit BOM-Zeichen in Python”

Stücklistenzeichen sollten bei der Decodierung von UTF-16 automatisch gelöscht werden, aber nicht UTF-8, sofern Sie nicht explizit die utf-8-sig Codierung verwenden. Du könntest so etwas ausprobieren:

 import io import chardet import codecs bytes = min(32, os.path.getsize(filename)) raw = open(filename, 'rb').read(bytes) if raw.startswith(codecs.BOM_UTF8): encoding = 'utf-8-sig' else: result = chardet.detect(raw) encoding = result['encoding'] infile = io.open(filename, mode, encoding=encoding) data = infile.read() infile.close() print(data) 

Ich habe einen nummerierten BOM-basierten Detektor auf der Grundlage von Chepers Antwort komponiert. Es genügt im üblichen Anwendungsfall, wo Daten entweder in einer bekannten lokalen Kodierung oder Unicode mit Stückliste sein können. (Das ist, was Text-Editoren in der Regel produzieren):

 def detect_by_bom(path,default): with open(path, 'rb') as f: raw = f.read(4) #will read less if the file is smaller for enc,boms in \ ('utf-8-sig',(codecs.BOM_UTF8,)),\ ('utf-16',(codecs.BOM_UTF16_LE,codecs.BOM_UTF16_BE)),\ ('utf-32',(codecs.BOM_UTF32_LE,codecs.BOM_UTF32_BE)): if any(raw.startswith(bom) for bom in boms): return enc return default 

chardet erkennt BOM_UTF8 automatisch seit 2.3.0 Version veröffentlicht am 7. Oktober 2014 :

 #!/usr/bin/env python import chardet # $ pip install chardet # detect file encoding with open(filename, 'rb') as file: raw = file.read(32) # at most 32 bytes are returned encoding = chardet.detect(raw)['encoding'] with open(filename, encoding=encoding) as file: text = file.read() print(text) 

Anmerkung: chardet kann 'UTF-XXLE' , 'UTF-XXBE' , die die Stückliste im Text verlassen. 'LE' , 'BE' sollte entkleidet werden, um es zu vermeiden – obwohl es einfacher ist, Stückliste selbst zu diesem Zeitpunkt zu entdecken, zB wie bei @ ivan_pozdeevs Antwort .

Um UnicodeEncodeError zu vermeiden, während Sie Unicode-Text in Windows-Konsole drucken, finden Sie unter Python, Unicode und die Windows-Konsole .

Eine Variante von @ ivan_pozdeevs Antwort auf Strings / Ausnahmen (statt Dateien). Ich beschäftige mich mit Unicode-HTML-Inhalten, die in einer Python-Ausnahme gefüllt wurden (siehe http://bugs.python.org/issue2517 )

 def detect_encoding(bytes_str): for enc, boms in \ ('utf-8-sig',(codecs.BOM_UTF8,)),\ ('utf-16',(codecs.BOM_UTF16_LE,codecs.BOM_UTF16_BE)),\ ('utf-32',(codecs.BOM_UTF32_LE,codecs.BOM_UTF32_BE)): if (any(bytes_str.startswith(bom) for bom in boms): return enc return 'utf-8' # default def safe_exc_to_str(exc): try: return str(exc) except UnicodeEncodeError: return unicode(exc).encode(detect_encoding(exc.content)) 

Alternativ ist dieser viel einfachere Code in der Lage, nicht-ascii Zeichen ohne viel Aufhebens zu löschen:

 def just_ascii(str): return unicode(str).encode('ascii', 'ignore') 

Es gibt keinen Grund zu prüfen, ob eine Stückliste existiert oder nicht, utf-8-sig verwaltet das für Sie und verhält sich genau wie utf-8 wenn die Stückliste nicht existiert:

 # Standard UTF-8 without BOM >>> b'hello'.decode('utf-8') 'hello' >>> b'hello'.decode('utf-8-sig') 'hello' # BOM encoded UTF-8 >>> b'\xef\xbb\xbfhello'.decode('utf-8') '\ufeffhello' >>> b'\xef\xbb\xbfhello'.decode('utf-8-sig') 'hello' 
  • Unicode-Text in eine Textdatei schreiben?
  • Python, um in UTF8 auf Windows XP mit der Konsole zu drucken
  • So entfernen Sie String Unicode aus der Liste
  • Unicode-Dateinamen unter Windows mit Python & subprocess.Popen ()
  • Unicode (). Decodieren ('utf-8', 'ignore'), der UnicodeEncodeError anhebt
  • Python - Wie kann ich Bytes in einer Datei ändern?
  • UnicodeEncode Fehler bei der Bereitstellung von Python Application
  • Python Unicode in und aus IDE
  • Unicode-Identifikatoren in Python?
  • Datei öffnen Fehler mit Codec utf-8 in python
  • Scrapy Spider: Umgang mit Seiten, die falsch definierte Zeichencodierung haben
  • Python ist die beste Programmiersprache der Welt.