Ich habe einige Gehirnfehler beim Verstehen des Lesens und Schreibens von Text in eine Datei (Python 2.4).
# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)
("u'Capit \ xe1n", "Capit \ xc3 \ xa1n")
print ss, ss8
print >> open('f1','w'), ss8
>>> file('f1').read()
'Capit\xc3\xa1n\n'
Also tippe ich Capit\xc3\xa1n
in meinen Lieblingseditor in Datei f2.
Dann:
>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'
Was verstehe ich hier nicht? Offensichtlich fehlt mir ein wichtiges Stück Magie (oder ein gesunder Menschenverstand). Was gibt man in Textdateien ein, um korrekte Konvertierungen zu erzielen?
Was ich hier wirklich nicht verstehe, ist der Sinn der UTF-8-Darstellung, wenn Sie Python nicht dazu bringen können, es zu erkennen, wenn es von außen kommt. Vielleicht sollte ich einfach JSON die Zeichenfolge ausgeben und diese stattdessen verwenden, da dies eine aufstellbare Darstellung hat! Gibt es eine ASCII-Darstellung dieses Unicode-Objekts, die Python erkennt und dekodiert, wenn es aus einer Datei eingeht? Wenn ja, wie bekomme ich es?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
Dies ist ein Unicode-CodepunktU+00e1
, der je nach Zeichenkodierung mit 1 oder mehr Bytes dargestellt werden kann (in utf-8 sind es 2 Bytes).b'\xe1'
ist ein Byte (eine Zahl 225), welcher Buchstabe, falls vorhanden, von der Zeichencodierung abhängt, die zum Decodieren verwendet wird, z. B.б
(U+0431
) in cp1251,с
(U+0441
) in cp866 usw.Anstatt mit den Codierungs- und Decodierungsmethoden herumzuspielen, fällt es mir leichter, die Codierung beim Öffnen der Datei anzugeben. Das in Python 2.6 hinzugefügte
io
Modul bietet eineio.open
Funktion mit einem Codierungsparameter.Verwenden Sie die Methode open aus dem
io
Modul.Nach dem Aufruf der Funktion read () von f wird dann ein codiertes Unicode-Objekt zurückgegeben.
Beachten Sie, dass die
io.open
Funktion in Python 3 ein Alias für die integrierteopen
Funktion ist. Die integrierte Öffnungsfunktion unterstützt nur das Codierungsargument in Python 3, nicht in Python 2.Bearbeiten: Zuvor empfahl diese Antwort das Codecs- Modul. Die Codecs Modul kann zu Problemen führen , wenn das Mischen
read()
undreadline()
, so dass diese Antwort empfiehlt nun das io - Modul statt.Verwenden Sie die Methode open aus dem Codecs-Modul.
Nach dem Aufruf der Funktion read () von f wird dann ein codiertes Unicode-Objekt zurückgegeben.
Wenn Sie die Codierung einer Datei kennen, ist die Verwendung des Codecs-Pakets weniger verwirrend.
Sehen http://docs.python.org/library/codecs.html#codecs.open
quelle
open(file,'w')
tuncodecs.open(file,'w','utf-8')
gelöstcodecs.open(...)
Methode auch vollständig demwith open(...):
Stil, bei dem eswith
darum geht, die Datei zu schließen, nachdem alles erledigt ist? Es scheint sowieso zu funktionieren.with codecs.open(...) as f:
ganze Zeit.Jetzt brauchen Sie nur noch Python3
open(Filename, 'r', encoding='utf-8')
[Bearbeiten am 10.02.2016 zur angeforderten Klarstellung]
Python3 hat den Codierungsparameter zu seiner offenen Funktion hinzugefügt . Die folgenden Informationen zur Öffnungsfunktion finden Sie hier: https://docs.python.org/3/library/functions.html#open
Durch Hinzufügen
encoding='utf-8'
als Parameter zur Öffnungsfunktion erfolgt das Lesen und Schreiben der Datei als utf8 (dies ist jetzt auch die Standardcodierung für alles, was in Python ausgeführt wird).quelle
codecs.open('somefile', encoding='utf-8')
obAlso habe ich eine Lösung für das gefunden, wonach ich suche:
Es gibt einige ungewöhnliche Codecs, die hier nützlich sind. Diese spezielle Lesart ermöglicht es, UTF-8-Darstellungen aus Python heraus zu übernehmen, sie in eine ASCII-Datei zu kopieren und sie in Unicode einlesen zu lassen. Bei der Dekodierung "String-Escape" werden die Schrägstriche nicht verdoppelt.
Dies ermöglicht die Art von Rundreise, die ich mir vorgestellt habe.
quelle
(codecs.open(file,"r","utf-8")
und einfachopen(file,"r").read().decode("utf-8")
und beide haben perfekt funktioniert.quelle
Tatsächlich funktionierte dies für mich beim Lesen einer Datei mit UTF-8-Codierung in Python 3.2:
quelle
Um eine Unicode-Zeichenfolge einzulesen und dann an HTML zu senden, habe ich Folgendes getan:
Nützlich für http-Server mit Python-Unterstützung.
quelle
Sie sind über das allgemeine Problem mit Codierungen gestolpert: Wie kann ich feststellen, in welcher Codierung eine Datei enthalten ist?
Antwort: Dies ist nur möglich, wenn das Dateiformat dies vorsieht. XML beginnt beispielsweise mit:
Dieser Header wurde sorgfältig ausgewählt, damit er unabhängig von der Codierung gelesen werden kann. In Ihrem Fall gibt es keinen solchen Hinweis, daher haben weder Ihr Editor noch Python eine Ahnung, was los ist. Daher müssen Sie das
codecs
Modul verwenden und verwendencodecs.open(path,mode,encoding)
, das das fehlende Bit in Python bereitstellt.Bei Ihrem Editor müssen Sie prüfen, ob er eine Möglichkeit zum Festlegen der Codierung einer Datei bietet.
Der Zweck von UTF-8 besteht darin, 21-Bit-Zeichen (Unicode) als 8-Bit-Datenstrom codieren zu können (da dies das einzige ist, was alle Computer auf der Welt verarbeiten können). Da die meisten Betriebssysteme jedoch älter sind als die Unicode-Ära, verfügen sie nicht über geeignete Tools, um die Codierungsinformationen an Dateien auf der Festplatte anzuhängen.
Das nächste Problem ist die Darstellung in Python. Dies wird im Kommentar von heikogerlach perfekt erklärt . Sie müssen verstehen, dass Ihre Konsole nur ASCII anzeigen kann. Um Unicode oder irgendetwas> = Zeichencode 128 anzuzeigen, muss ein Escape-Mittel verwendet werden. In Ihrem Editor dürfen Sie nicht die maskierte Anzeigezeichenfolge eingeben, sondern die Bedeutung der Zeichenfolge (in diesem Fall müssen Sie den Umlaut eingeben und die Datei speichern).
Sie können jedoch die Python-Funktion eval () verwenden, um eine maskierte Zeichenfolge in eine Zeichenfolge umzuwandeln:
Wie Sie sehen können, wurde die Zeichenfolge "\ xc3" in ein einzelnes Zeichen umgewandelt. Dies ist jetzt eine 8-Bit-Zeichenfolge, UTF-8-codiert. So erhalten Sie Unicode:
Gregg Lind fragte: Ich denke, hier fehlen einige Teile: Die Datei f2 enthält: hex:
codecs.open('f2','rb', 'utf-8')
Liest sie beispielsweise alle in separaten Zeichen (erwartet). Gibt es eine Möglichkeit, in eine Datei in ASCII zu schreiben, die funktionieren würde?Antwort: Das hängt davon ab, was Sie meinen. ASCII kann keine Zeichen> 127 darstellen. Sie müssen also sagen, dass die nächsten Zeichen etwas Besonderes bedeuten, wie es die Sequenz "\ x" tut. Es heißt: Die nächsten beiden Zeichen sind der Code eines einzelnen Zeichens. "\ u" macht dasselbe mit vier Zeichen, um Unicode bis zu 0xFFFF (65535) zu codieren.
Sie können Unicode also nicht direkt in ASCII schreiben (da ASCII einfach nicht dieselben Zeichen enthält). Sie können es als Escapezeichenfolge schreiben (wie in f2). In diesem Fall kann die Datei als ASCII dargestellt werden. Oder Sie können es als UTF-8 schreiben. In diesem Fall benötigen Sie einen sicheren 8-Bit-Stream.
Ihre Lösung
decode('string-escape')
funktioniert, aber Sie müssen wissen, wie viel Speicher Sie verwenden: Dreifache Menge an Speichercodecs.open()
.Denken Sie daran, dass eine Datei nur eine Folge von Bytes mit 8 Bits ist. Weder die Bits noch die Bytes haben eine Bedeutung. Sie sagen "65 bedeutet 'A'". Da
\xc3\xa1
"à" werden sollte, der Computer jedoch keine Mittel zum Wissen hat, müssen Sie dies durch Angabe der Codierung angeben, die beim Schreiben der Datei verwendet wurde.quelle
mit Ausnahme von
codecs.open()
kannio.open()
man mit Python2 oder Python3 arbeiten, um Unicode-Dateien zu lesen / schreibenBeispiel
quelle
with io.open('data.txt', 'w', 'utf-8') as file:
und einen Fehler bekommen :TypeError: an integer is required
. Nachdem ich zu gewechselt habewith io.open('data.txt', 'w', encoding='utf-8') as file:
und es funktioniert hat.Nun, Ihr bevorzugter Texteditor erkennt nicht, dass
\xc3\xa1
es sich um Zeichenliterale handeln soll, interpretiert sie jedoch als Text. Deshalb erhalten Sie in der letzten Zeile die doppelten Backslashes - es ist jetzt ein echter Backslash +xc3
usw. in Ihrer Datei.Wenn Sie codierte Dateien in Python lesen und schreiben möchten, verwenden Sie am besten das Codecs- Modul.
Das Einfügen von Text zwischen dem Terminal und den Anwendungen ist schwierig, da Sie nicht wissen, welches Programm Ihren Text mit welcher Codierung interpretiert. Sie könnten Folgendes versuchen:
Fügen Sie diese Zeichenfolge dann in Ihren Editor ein und stellen Sie sicher, dass sie mit Latin-1 gespeichert wird. Unter der Annahme, dass die Zwischenablage die Zeichenfolge nicht verstümmelt, sollte der Roundtrip funktionieren.
quelle
Die \ x .. -Sequenz ist etwas, das für Python spezifisch ist. Es ist keine universelle Byte-Escape-Sequenz.
Wie Sie UTF-8-codiertes Nicht-ASCII tatsächlich eingeben, hängt von Ihrem Betriebssystem und / oder Ihrem Editor ab. So geht's in Windows . Damit OS X ein mit einem akuten Akzent eingibt, können Sie einfach option+ Edrücken A, und fast alle Texteditoren in OS X unterstützen UTF-8.
quelle
Sie können die ursprüngliche
open()
Funktion auch für die Arbeit mit Unicode-Dateien verbessern, indem Sie sie mithilfe derpartial
Funktion ersetzen . Das Schöne an dieser Lösung ist, dass Sie keinen alten Code ändern müssen. Es ist transparent.quelle
Ich habe versucht, iCal mit Python 2.7.9 zu analysieren :
Aber ich bekam:
und es wurde mit nur behoben:
(Jetzt kann es liké á böss drucken.)
quelle
Ich fand den einfachsten Ansatz, indem ich die Standardcodierung des gesamten Skripts in 'UTF-8' änderte:
jeder
open
,print
oder andere Aussage wird nur verwendenutf8
.Funktioniert zumindest für
Python 2.7.9
.Thx geht zu https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( schau dir das Ende an).
quelle