UnicodeDecodeError bei der Durchführung os.gehen
Bin ich immer die Fehlermeldung:
'ascii' codec can't decode byte 0x8b in position 14: ordinal not in range(128)
wenn Sie versuchen zu tun os.Fuss. Der Fehler tritt auf, weil einige der Dateien in einem Verzeichnis haben, das 0x8b (nicht-utf8-Zeichen in Ihnen. Die Dateien stammen von einem Windows-system (also die utf-16-Dateinamen), aber ich habe kopiert die Dateien auf einem Linux-system und bin mit python 2.7 (läuft auf Linux) zum Durchlaufen der Verzeichnisse.
Ich habe versucht, übergeben Sie eine unicode-start Pfad zum os.Weg, und alle die Dateien & dirs es generiert, werden unicode-Namen, bis es kommt zu einer nicht-utf8-Namen, und dann aus irgendeinem Grund, es nicht konvertieren Sie diese Namen in unicode und dann den code drosseln auf die utf-16-Namen. Gibt es trotzdem, um das problem zu lösen kurz manuell suchen und ändern Sie alle das beleidigende Namen?
Wenn es keine Lösung ist in python2.7, kann ein Skript geschrieben in Python ist3 zum Durchlaufen des Dateibaumes und beheben die schlechte Dateinamen durch die Konvertierung in utf-8 (durch entfernen der nicht-utf8-Zeichen)? N. B. es gibt viele nicht-utf8-Zeichen in den Namen neben 0x8b, so würde es brauchen, um die Arbeit in einer Allgemeinen Weise.
UPDATE: Die Tatsache, dass 0x8b ist nur noch ein btye char (nicht nur gültige ascii -) macht es noch rätselhafter. Ich habe überprüft, dass es ein problem der Konvertierung so ein string nach unicode, aber, dass eine unicode-version erstellt werden kann direkt. Zu Witz:
>>> test = 'a string \x8b with non-ascii'
>>> test
'a string \x8b with non-ascii'
>>> unicode(test)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 9: ordinal not in range(128)
>>>
>>> test2 = u'a string \x8b with non-ascii'
>>> test2
u'a string \x8b with non-ascii'
Hier ist ein traceback des Fehlers bin ich immer:
80. for root, dirs, files in os.walk(unicode(startpath)):
File "/usr/lib/python2.7/os.py" in walk
294. for x in walk(new_path, topdown, onerror, followlinks):
File "/usr/lib/python2.7/os.py" in walk
294. for x in walk(new_path, topdown, onerror, followlinks):
File "/usr/lib/python2.7/os.py" in walk
284. if isdir(join(top, name)):
File "/usr/lib/python2.7/posixpath.py" in join
71. path += '/' + b
Exception Type: UnicodeDecodeError at /admin/casebuilder/company/883/
Exception Value: 'ascii' codec can't decode byte 0x8b in position 14: ordinal not in range(128)
Die Wurzel des Problems tritt in der Liste der Dateien zurückgegeben, die von listdir (auf Zeile 276 von os.Fuß):
names = listdir(top)
Den Namen mit chars > 128 zurückgegeben, die als non-unicode-Zeichenfolgen.
- Ich denke, man könnte fangen Sie die Ausnahmen und diese separat behandeln?
- Können Sie den vollständigen traceback?
- Was meinst du mit "nicht-UTF8"? Byte 0x8b sicherlich ist nicht gültig als ASCII, aber wir würden sehen müssen, die folgenden bytes zu wissen, ob es gültig war, als UTF-8. Nur weil Sie gesehen haben, ein byte von 0x8b, bedeutet nicht, es versucht darzustellen U+008B als Charakter.
- versuchen:
os.walk(unicode(path))
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Recht, ich habe gerade einige Zeit damit verbracht zu Sortieren, die durch diese Fehler, und wordier Antworten hier sind nicht immer auf das zugrunde liegende Problem:
Das problem ist, wenn Sie eine unicode-Zeichenfolge in os.Fuß(), dann os.Spaziergang beginnt immer unicode zurück vom os.listdir() und versucht, Sie zu halten, als ASCII (also 'ascii' decode error"). Wenn es Sie trifft einer nur-unicode-Sonderzeichen, die str() kann nicht übersetzen, es wirft die Ausnahme.
Den Lösung ist die Kraft der Start-Pfad übergeben os.Spaziergang zu einem regulären string - d.h. os.zu Fuss(str(somepath)). Dies bedeutet, dass os.listdir gibt regelmäßige byte-wie strings und alles funktioniert so wie es soll.
Können Sie dieses problem reproduzieren (und zeigen es die Lösung funktioniert) trivial wie:
Gehen in die bash in einem Verzeichnis und führen Sie
touch $(echo -e "\x8b\x8bThis is a bad filename")
was machen einige test-Dateien.Führen Sie nun die folgenden Python-code (iPython Qt ist sehr nützlich für diese) in das gleiche Verzeichnis:
Und Sie erhalten ein UnicodeDecodeError.
Versuchen Sie jetzt:
Kein Fehler und Sie erhalten eine ausdrucken!
Damit der sichere Weg in Python 2.x sicherstellen, dass Sie nur unformatierten text zu os.walk(). Sie absolut sollte nicht pass unicode oder Dinge, die sein könnten, unicode, weil os.zu Fuss wird dann ersticken, wenn ein interner ascii-Konvertierung schlägt fehl.
Kann ich reproduzieren, die
os.listdir()
Verhalten:os.listdir(unicode_name)
gibt undecodable Einträge als bytes auf Python 2.7:Hinweis: der zweite name ist ein bytestring trotz
listdir()
's argument wird eine Unicode-Zeichenfolge.Python 3 löst undecodable Byte (bei Verwendung eines Dateisystem-Charakter-Codierung) Byte in Dateinamen über
surrogateescape
error handler (os.fsencode/os.fsdecode
). Sehen PEP-383: die Nicht-decodable Bytes in-System-Charakter Schnittstellen:Hinweis: beide Strings sind in Unicode (Python 3). Und
surrogateescape
error-handler verwendet wurde, für den zweiten Namen. Um die original-bytes zurück:In Python 2 verwenden Sie Unicode-strings für Dateinamen unter Windows (Unicode-API), OS X (utf-8 erzwungen wird), und verwenden Sie bytestrings auf Linux und anderen Systemen.
os.walk()
; es gibt bytes. Sie Dekodieren konnte in Unicode später, wenn Sie denken, dass die Dateinamen werden nicht beschädigt (es sollte möglich sein, zu erraten, wird die Zeichen-Codierung, wenn Sie haben viele Namen).Dieses problem ergibt sich aus zwei fundamentalen Problemen. Die erste ist die Tatsache, dass Python 2.x Standard-Codierung ist 'ascii', während die Standard-Linux-encoding is 'utf8'. Sie können überprüfen, diese Kodierungen über:
Als os-Modul-Funktionen zurückgeben Verzeichnis Inhalt, nämlich os.walk & os.listdir gibt eine Liste von Dateien, die nur ascii-Dateinamen und nicht-ascii-Dateinamen der ascii-Kodierung von Dateinamen konvertiert Sie automatisch zu unicode. Die anderen sind nicht. Also, das Ergebnis ist eine Liste, die eine Mischung aus unicode-und str-Objekte. Es ist der str-Objekte, die verursachen können Probleme auf der ganzen Linie. Da Sie nicht ascii -, python hat keine Möglichkeit zu wissen, welche Codierung zu verwenden, und können daher nicht decodiert werden automatisch in unicode.
Daher, bei der Durchführung von gemeinsamen Operationen wie os.Pfad(Verzeichnis und Datei), wo dir ist unicode und Datei ist eine kodierte str, dieser Aufruf schlägt fehl, wenn die Datei nicht ascii-codiert sind (Standardeinstellung). Die Lösung ist zu prüfen, jeder mit dem Namen, sobald Sie abgerufen werden und decodieren der str (codiert sind) Objekte in unicode unter Verwendung der entsprechenden Kodierung.
Das ist das erste problem und seine Lösung. Die zweite ist etwas schwieriger. Da die Dateien ursprünglich von einem Windows-system, sind Ihre Dateinamen wahrscheinlich eine Kodierung genannt windows-1252. Ein einfaches Mittel der überprüfung ist zu nennen:
Wenn eine gültige unicode-version der Ergebnisse, die Sie wahrscheinlich haben die richtige Kodierung. Sie können weiter zu überprüfen, ob durch den Aufruf drucken auf die unicode-version als auch und sehen die richtige mit dem Namen gerendert.
Eine Letzte Falte. In einem Linux-system mit Dateien von Windows-Herkunft, es ist möglich oder sogar wahrscheinlich, eine Mischung der windows-1252 und utf8 Codierungen. Es gibt zwei Möglichkeiten des Umgangs mit dieser Mischung. Die erste und vorzuziehen ist, um zu laufen:
wo ist das VERZEICHNIS, das enthält die Dateien, die Konvertierung benötigen.Dieser Befehl konvertiert beliebigen windows-1252-kodierte Dateinamen auf utf8. Es führt eine intelligente Konvertierung, das heißt, wenn ein Dateiname ist bereits utf-8 (oder ascii), wird es nichts tun.
Die alternative (wenn man nicht tun kann diese Konvertierung für einige Grund auch immer), etwas ähnliches zu tun on-the-fly in python. Zu Witz:
Die Funktion versucht ein utf8-Dekodierung ersten. Wenn es ausfällt, dann fällt es zurück auf den windows-1252-version. Verwenden Sie diese Funktion nach einem os-call-zurückgeben einer Liste von Dateien:
Ich persönlich fand das gesamte Thema unicode und Kodierung sehr verwirrend, bis ich Las dieses wunderbare und einfache Anleitung:
http://farmdev.com/talks/unicode/
Ich empfehle es für alle, die kämpfen mit unicode Probleme.
\x8 ist keine gültige utf-8-Kodierung Zeichen. os.Pfad erwartet, dass die Dateinamen in utf-8. Wenn Sie möchten, um Zugriff auf ungültige Dateinamen, müssen Sie die os.Pfad.gehen Sie die nicht-unicode-startpath auf diese Weise wird das os-Modul werden nicht die utf8-Dekodierung. Sie müssten es selbst tun und entscheiden, was mit den Dateinamen, die enthalten falsche Zeichen.
I. e.:
Nach Prüfung der Quelle des Fehlers etwas passiert, in dem C-code-routine listdir gibt die nicht-unicode-Dateinamen, wenn Sie nicht den standard-ascii. Nur der fix also ist zu tun gezwungen decodieren der Verzeichnis-Liste in os.gehen, das erfordert ein Ersatz des os.Fuss. Diese Ersatz-Funktion:
Durch das hinzufügen der Zeile:
Namen = [name.decode('utf8','ignore') for name in names]
alle Namen sind richtige ascii - & unicode, und alles ordnungsgemäß funktioniert.
Ist eine große Frage bleibt aber - wie kann das gelöst werden, ohne Rückgriff auf dieses hack??
Ich habe dieses problem wenn Gebrauch
os.walk
auf einige Verzeichnisse mit Chinesisch (unicode -) Namen. Ich habe implementiert die walk-Funktion selbst, wie folgt, das funktionierte mit unicode-dir/Datei-Namen.