u '\ ufeff' in Python-String

152

Ich erhalte eine Fehlermeldung mit folgendem Muster:

UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 155: ordinal not in range(128)

u'\ufeff'Ich bin mir nicht sicher, was es ist. Es zeigt sich, wenn ich Web Scraping mache. Wie kann ich Abhilfe schaffen? Die .replace()String-Methode funktioniert nicht.

James Hallen
quelle
6
Woher kommt diese Eingabe? Was versuchst du zu tun? Bitte geben Sie Ihren Python-Code an.
7
Übrigens finde ich, dass .replace () in modernem Python funktioniert, wenn ich mich an den Unicode-Indikator erinnere: s.replace (u '\ ufeff', '')
Doug Bradshaw
@DougBradshaw Wenn Sie "moderne Python" sagen, meinen Sie 2,7+ oder 3,0+?
Teewuane
Guter Punkt. Bedeutung 2,7+.
Doug Bradshaw

Antworten:

184

Das Unicode-Zeichen U+FEFFist das Byte Order Mark (BOM) und wird verwendet, um den Unterschied zwischen Big- und Little-Endian-UTF-16-Codierung zu erkennen. Wenn Sie die Webseite mit dem richtigen Codec dekodieren, entfernt Python sie für Sie. Beispiele:

#!python2
#coding: utf8
u = u'ABC'
e8 = u.encode('utf-8')        # encode without BOM
e8s = u.encode('utf-8-sig')   # encode with BOM
e16 = u.encode('utf-16')      # encode with BOM
e16le = u.encode('utf-16le')  # encode without BOM
e16be = u.encode('utf-16be')  # encode without BOM
print 'utf-8     %r' % e8
print 'utf-8-sig %r' % e8s
print 'utf-16    %r' % e16
print 'utf-16le  %r' % e16le
print 'utf-16be  %r' % e16be
print
print 'utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8')
print 'utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig')
print 'utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16')
print 'utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le')

Beachten Sie, dass EF BB BFes sich um eine UTF-8-codierte Stückliste handelt. Es ist für UTF-8 nicht erforderlich, dient jedoch nur als Signatur (normalerweise unter Windows).

Ausgabe:

utf-8     'ABC'
utf-8-sig '\xef\xbb\xbfABC'
utf-16    '\xff\xfeA\x00B\x00C\x00'    # Adds BOM and encodes using native processor endian-ness.
utf-16le  'A\x00B\x00C\x00'
utf-16be  '\x00A\x00B\x00C'

utf-8  w/ BOM decoded with utf-8     u'\ufeffABC'    # doesn't remove BOM if present.
utf-8  w/ BOM decoded with utf-8-sig u'ABC'          # removes BOM if present.
utf-16 w/ BOM decoded with utf-16    u'ABC'          # *requires* BOM to be present.
utf-16 w/ BOM decoded with utf-16le  u'\ufeffABC'    # doesn't remove BOM if present.

Beachten Sie, dass für den utf-16Codec eine Stückliste erforderlich sein muss, oder Python nicht weiß, ob es sich bei den Daten um Big- oder Little-Endian-Daten handelt.

Mark Tolonen
quelle
200

Ich bin auf Python 3 darauf gestoßen und habe diese Frage (und Lösung) gefunden ) gefunden. Beim Öffnen einer Datei unterstützt Python 3 das Schlüsselwort encoding, um die Codierung automatisch zu verarbeiten.

Ohne sie ist die Stückliste im Leseergebnis enthalten:

>>> f = open('file', mode='r')
>>> f.read()
'\ufefftest'

Bei korrekter Codierung wird die Stückliste im Ergebnis weggelassen:

>>> f = open('file', mode='r', encoding='utf-8-sig')
>>> f.read()
'test'

Nur meine 2 Cent.

siebz0r
quelle
13
Vielen Dank, dies ist die eigentliche Lösung und sollte die akzeptierte Antwort sein. Während dies ein guter Einblick ist, warum die Saite dort ist, suchen die meisten Leute, die hierher kommen, nach einer einfachen Lösung, und das ist es.
Neurino
3
Hatte das gleiche Problem mit dem CSV DictReader beim Lesen einer aus Excel gespeicherten CSV-Datei.
LArntz
1
Ja, Excel (sogar "csv", das von Excel generiert wird) ist wirklich ein heißes Durcheinander.
Fischadler
4

Dieses Zeichen ist die Stückliste oder "Byte Order Mark". Es wird normalerweise als die ersten paar Bytes einer Datei empfangen und zeigt Ihnen, wie Sie die Codierung der restlichen Daten interpretieren. Sie können das Zeichen einfach entfernen, um fortzufahren. Da der Fehler besagt, dass Sie versucht haben, in 'ascii' zu konvertieren, sollten Sie wahrscheinlich eine andere Codierung für alles auswählen, was Sie versucht haben.

swstephe
quelle
4

Der Inhalt, den Sie kratzen, ist eher in Unicode als in ASCII-Text codiert, und Sie erhalten ein Zeichen, das nicht in ASCII konvertiert wird. Die richtige 'Übersetzung' hängt davon ab, was die ursprüngliche Webseite dachte. Die Unicode-Seite von Python bietet Hintergrundinformationen zur Funktionsweise.

Versuchen Sie, das Ergebnis zu drucken oder in eine Datei zu schreiben? Der Fehler deutet darauf hin , dass die Daten, die das Problem verursachen, geschrieben und nicht gelesen werden. Diese Frage ist ein guter Ort, um nach Korrekturen zu suchen.

theodox
quelle
0

Hier basiert auf der Antwort von Mark Tolonen. Die Zeichenfolge enthielt verschiedene Sprachen des Wortes 'test', die durch '|' getrennt sind, sodass Sie den Unterschied erkennen können.

u = u'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
e8 = u.encode('utf-8')        # encode without BOM
e8s = u.encode('utf-8-sig')   # encode with BOM
e16 = u.encode('utf-16')      # encode with BOM
e16le = u.encode('utf-16le')  # encode without BOM
e16be = u.encode('utf-16be')  # encode without BOM
print('utf-8     %r' % e8)
print('utf-8-sig %r' % e8s)
print('utf-16    %r' % e16)
print('utf-16le  %r' % e16le)
print('utf-16be  %r' % e16be)
print()
print('utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8'))
print('utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig'))
print('utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16'))
print('utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le'))

Hier ist ein Testlauf:

>>> u = u'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> e8 = u.encode('utf-8')        # encode without BOM
>>> e8s = u.encode('utf-8-sig')   # encode with BOM
>>> e16 = u.encode('utf-16')      # encode with BOM
>>> e16le = u.encode('utf-16le')  # encode without BOM
>>> e16be = u.encode('utf-16be')  # encode without BOM
>>> print('utf-8     %r' % e8)
utf-8     b'ABCtest\xce\xb2\xe8\xb2\x9d\xe5\xa1\x94\xec\x9c\x84m\xc3\xa1sb\xc3\xaata|test|\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1|\xe6\xb5\x8b\xe8\xaf\x95|\xe6\xb8\xac\xe8\xa9\xa6|\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88|\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa5\x80\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb7\xe0\xa4\xbe|\xe0\xb4\xaa\xe0\xb4\xb0\xe0\xb4\xbf\xe0\xb4\xb6\xe0\xb5\x8b\xe0\xb4\xa7\xe0\xb4\xa8|\xd7\xa4\xd6\xbc\xd7\xa8\xd7\x95\xd7\x91\xd7\x99\xd7\xa8\xd7\x9f|ki\xe1\xbb\x83m tra|\xc3\x96l\xc3\xa7ek|'
>>> print('utf-8-sig %r' % e8s)
utf-8-sig b'\xef\xbb\xbfABCtest\xce\xb2\xe8\xb2\x9d\xe5\xa1\x94\xec\x9c\x84m\xc3\xa1sb\xc3\xaata|test|\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1|\xe6\xb5\x8b\xe8\xaf\x95|\xe6\xb8\xac\xe8\xa9\xa6|\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88|\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa5\x80\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb7\xe0\xa4\xbe|\xe0\xb4\xaa\xe0\xb4\xb0\xe0\xb4\xbf\xe0\xb4\xb6\xe0\xb5\x8b\xe0\xb4\xa7\xe0\xb4\xa8|\xd7\xa4\xd6\xbc\xd7\xa8\xd7\x95\xd7\x91\xd7\x99\xd7\xa8\xd7\x9f|ki\xe1\xbb\x83m tra|\xc3\x96l\xc3\xa7ek|'
>>> print('utf-16    %r' % e16)
utf-16    b"\xff\xfeA\x00B\x00C\x00t\x00e\x00s\x00t\x00\xb2\x03\x9d\x8cTX\x04\xc7m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x00'\x06.\x06*\x06(\x06'\x061\x06|\x00Km\xd5\x8b|\x00,nf\x8a|\x00\xc60\xb90\xc80|\x00*\t0\t@\t\x15\tM\t7\t>\t|\x00*\r0\r?\r6\rK\r'\r(\r|\x00\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x05|\x00k\x00i\x00\xc3\x1em\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|\x00"
>>> print('utf-16le  %r' % e16le)
utf-16le  b"A\x00B\x00C\x00t\x00e\x00s\x00t\x00\xb2\x03\x9d\x8cTX\x04\xc7m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x00'\x06.\x06*\x06(\x06'\x061\x06|\x00Km\xd5\x8b|\x00,nf\x8a|\x00\xc60\xb90\xc80|\x00*\t0\t@\t\x15\tM\t7\t>\t|\x00*\r0\r?\r6\rK\r'\r(\r|\x00\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x05|\x00k\x00i\x00\xc3\x1em\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|\x00"
>>> print('utf-16be  %r' % e16be)
utf-16be  b"\x00A\x00B\x00C\x00t\x00e\x00s\x00t\x03\xb2\x8c\x9dXT\xc7\x04\x00m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x06'\x06.\x06*\x06(\x06'\x061\x00|mK\x8b\xd5\x00|n,\x8af\x00|0\xc60\xb90\xc8\x00|\t*\t0\t@\t\x15\tM\t7\t>\x00|\r*\r0\r?\r6\rK\r'\r(\x00|\x05\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x00|\x00k\x00i\x1e\xc3\x00m\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|"
>>> print()

>>> print('utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8'))
utf-8  w/ BOM decoded with utf-8     '\ufeffABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig'))
utf-8  w/ BOM decoded with utf-8-sig 'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16'))
utf-16 w/ BOM decoded with utf-16    'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le'))
utf-16 w/ BOM decoded with utf-16le  '\ufeffABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'

Es ist wert zu wissen, dass nur beide utf-8-sigund utf-16die ursprüngliche Zeichenfolge nach beiden encodeund zurückbekommen decode.

caot
quelle
-3

Dieses Problem tritt im Wesentlichen auf, wenn Sie Ihren Python-Code in einer UTF-8- oder UTF-16-Codierung speichern , da Python am Anfang des Codes automatisch ein Sonderzeichen hinzufügt (das von den Texteditoren nicht angezeigt wird), um das Codierungsformat zu identifizieren. Wenn Sie jedoch versuchen, den Code auszuführen, wird in Zeile 1 der Syntaxfehler angezeigt, dh der Code wird gestartet, da der Python-Compiler die ASCII-Codierung versteht . Wenn Sie den Code der Datei mit der Funktion read () anzeigen, wird am Anfang des zurückgegebenen Codes '\ ufeff' angezeigt. Die einfachste Lösung für dieses Problem besteht darin , die Codierung wieder auf ASCII-Codierung zu ändern(Dazu können Sie Ihren Code in einen Notizblock kopieren und speichern. Denken Sie daran! Wählen Sie die ASCII-Codierung ... Ich hoffe, dies wird helfen.

Jagdish Chauhan
quelle