Beachten Sie, dass dies codecs.open()in 3.x veraltet ist, da open()ein encodingArgument gewonnen wird.
Ignacio Vazquez-Abrams
Es gibt auch einen dritten Weg (mindestens in Python 2.x): `f = Datei (Dateiname) '
Adam Parkin
1
@ IgnacioVazquez-Abrams Gibt es einen Link, der codecs.open()veraltet ist? Ich denke nicht, dass dies in Python3-Dokumenten: docs.python.org/3.7/library/codecs.html
Varela
1
@varela: Auf der von Ihnen erwähnten Python-Dokumentationsseite heißt es: "Das eingebaute open () und das zugehörige io-Modul sind der empfohlene Ansatz für die Arbeit mit codierten Textdateien"
Luciano Ramalho,
Antworten:
82
Seit Python 2.6 ist eine gute Praxis zu verwenden io.open(), die auch ein encodingArgument wie das jetzt veraltete nimmt codecs.open(). In Python 3 io.openist ein Alias für das open()eingebaute. Funktioniert also io.open()in Python 2.6 und allen späteren Versionen, einschließlich Python 3.4. Siehe Dokumente: http://docs.python.org/3.4/library/io.html
Nun, für die ursprüngliche Frage: beim Lesen Text (einschließlich „Klartext“, HTML, XML und JSON) in Python 2 Sie sollten immer verwenden io.open()mit einer expliziten Kodierung oder open()mit einer expliziten Kodierung in Python 3. Doing so Mittel erhalten Sie richtig Unicode dekodiert oder sofort einen Fehler angezeigt, was das Debuggen erheblich erleichtert.
Reiner ASCII "Klartext" ist ein Mythos aus der fernen Vergangenheit. Der richtige englische Text verwendet geschweifte Anführungszeichen, Striche, Aufzählungszeichen, € (Euro-Zeichen) und sogar Diaeresis (¨). Sei nicht naiv! (Und vergessen wir nicht das Fassadenmuster!)
Da reines ASCII keine echte Option ist, ist open()eine explizite Codierung nur zum Lesen von Binärdateien sinnvoll .
@ForeverWintr Die Antwort ist ziemlich klar: Verwenden Sie sie io.open()für Text und open()nur für Binärdateien. Die Implikation ist, dass dies überhaupt codecs.open()nicht bevorzugt wird.
Bdoserror
2
@Bdoserror, da ist eindeutig eine Antwort drin, aber es ist keine Antwort auf die gestellte Frage. Die Frage betraf den Unterschied zwischen openund codecs.openund insbesondere, wann letzteres dem ersteren vorzuziehen ist. Eine Antwort, die nicht einmal erwähnt wird, codecs.openkann diese Frage nicht beantworten.
ForeverWintr
3
@ForeverWintr Wenn das OP die falsche Frage gestellt hat (dh mit der Annahme, dass codecs.open()die Verwendung korrekt war), gibt es keine "richtige" Antwort darauf, wann sie verwendet werden soll. Die Antwort ist io.open()stattdessen zu verwenden . Es ist wie wenn ich frage "Wann sollte ich einen Schraubenschlüssel verwenden, um einen Nagel in eine Wand zu schlagen?". Die richtige Antwort lautet "Hammer benutzen".
Bdoserror
20
Persönlich benutze ich immer , es codecs.opensei denn, es gibt einen klar identifizierten Bedarf open**. Der Grund ist, dass ich so oft gebissen wurde, weil sich utf-8-Eingaben in meine Programme eingeschlichen haben. "Oh, ich weiß nur, dass es immer ASCII sein wird" ist eine Annahme, die oft gebrochen wird.
Die Annahme von 'utf-8' als Standardcodierung ist meiner Erfahrung nach eine sicherere Standardauswahl, da ASCII als UTF-8 behandelt werden kann, aber das Gegenteil ist nicht der Fall. Und in jenen Fällen, in denen ich wirklich weiß , dass die Eingabe ASCII ist, tue ich dies immer noch, codecs.openda ich fest davon überzeugt bin, dass "explizit besser als implizit" ist .
** - in Python 2.x, wie der Kommentar zu der Frage in Python 3 openersetztcodecs.open
Was ich nicht wirklich verstehe, ist, warum openmanchmal sehr gut mit den UTF-8-codierten nicht-lateinischen Zeichen des Unicode-Sets
umgegangen werden kann
Das macht für mich Sinn. io.opennimmt keinen Kodierungsparameter von dem, was ich in Python 2.7.5 sehen kann
radtek
1
@radtek, Sie haben Recht, dass dies nicht dokumentiert ist; (zumindest in 2.7.12) io.openakzeptiert encodingund newlineparametrisiert sie jedoch und interpretiert sie wie Python 3. Im Gegensatz zu codecs.open, eine Datei geöffnet mit io.openerhöhen wird TypeError: write() argument 1 must be unicode, not strauch in Python 2.7 , wenn Sie zu schreiben versuchen str( bytes) zu. Eine mit geöffnete Datei codecs.openversucht stattdessen eine implizite Konvertierung in unicode, was häufig zu verwirrenden UnicodeDecodeErrors führt.
Jochietoch
9
In Python 2 gibt es Unicode-Zeichenfolgen und Bytestrings. Wenn Sie nur Bytestrings verwenden, können Sie in eine Datei lesen / schreiben, die mit open()ganz gut geöffnet wurde . Immerhin sind die Zeichenfolgen nur Bytes.
Das Problem tritt auf, wenn Sie beispielsweise eine Unicode-Zeichenfolge haben und Folgendes tun:
>>> example = u'Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)Traceback(most recent call last):File"<stdin>", line 1,in<module>UnicodeEncodeError:'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
Hier codieren Sie also offensichtlich entweder explizit Ihre Unicode-Zeichenfolge in utf-8 oder Sie verwenden codecs.opendies, um dies transparent für Sie zu tun.
Wenn Sie immer nur Bytestrings verwenden, gibt es keine Probleme:
>>> example ='Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)>>>
Dies ist komplizierter, da beim Verketten einer Unicode- und Bytestring-Zeichenfolge mit dem +Operator eine Unicode-Zeichenfolge angezeigt wird . Leicht von diesem gebissen zu werden.
codecs.openMag auch keine Bytestrings mit Nicht-ASCII-Zeichen, die übergeben werden:
codecs.open('test','w', encoding='utf-8').write('Μου αρέσει')Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/usr/lib/python2.7/codecs.py", line 691,in write
return self.writer.write(data)File"/usr/lib/python2.7/codecs.py", line 351,in write
data, consumed = self.encode(object, self.errors)UnicodeDecodeError:'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
Der Ratschlag zu Zeichenfolgen für Eingabe / Ausgabe lautet normalerweise "so früh wie möglich in Unicode konvertieren und so spät wie möglich zurück in Bytestrings". Mit codecs.openkönnen Sie Letzteres sehr einfach tun.
Achten Sie nur darauf, dass Sie ihm Unicode-Zeichenfolgen und keine Bytestrings geben, die möglicherweise Nicht-ASCII-Zeichen enthalten.
Können Sie Ihr zweites Beispiel erklären? Es scheint mit Ihrem ersten Beispiel identisch zu sein. Warum sollte das Ergebnis anders sein?
Chris Johnson
Beachten Sie die Verwendung von u''im ersten Beispiel. Dies bedeutet, dass ich eine Unicode-Zeichenfolge erstellt habe, keinen Bytestring. Dies ist der Unterschied zwischen den beiden Beispielen. Im zweiten Beispiel erstelle ich einen Bytestring und das Schreiben eines davon in eine Datei ist in Ordnung. Eine Unicode-Zeichenfolge ist nicht in Ordnung, wenn Sie Zeichen außerhalb von ASCII verwenden.
Mandible79
7
Wenn Sie eine Datei mit einer bestimmten Codierung öffnen müssen, verwenden Sie das codecsModul.
Ich denke, alle Textdateien haben irgendwie eine bestimmte Codierung (:
Cedbeu
5
codecs.openIch nehme an, es ist nur ein Überbleibsel aus der Python 2Zeit, als das eingebaute Open eine viel einfachere Oberfläche und weniger Funktionen hatte. In Python 2 wird für opendie integrierte Funktion kein Codierungsargument verwendet. Wenn Sie also etwas anderes als den Binärmodus oder die Standardcodierung verwenden möchten, sollte codecs.open verwendet werden.
In Python 2.6kam das io-Modul zur Hilfe, um die Dinge ein bisschen einfacher zu machen. Nach der offiziellen Dokumentation
Newin version 2.6.The io module provides the Python interfaces to stream handling.UnderPython2.x, this is proposed as an alternative to the
built-in file object, but inPython3.x it is the default
interface to access files and streams.
Trotzdem kann ich mir codecs.openim aktuellen Szenario nur die Abwärtskompatibilität vorstellen. In allen anderen Szenarien (es sei denn, Sie verwenden Python <2.6) ist die Verwendung vorzuziehen io.open. Auch in Python 3.xio.openist das gleiche wiebuilt-in open
Hinweis:
Es gibt auch einen syntaktischen Unterschied zwischen codecs.openund io.open.
Nicht nur codecs.openund io.openunterscheiden sich in der Syntax, kehren sie Objekte unterschiedlicher Art. Funktioniert auch codecs.openimmer mit Dateien im Binärmodus.
Wombatonfire
4
Wenn Sie eine Binärdatei laden möchten, verwenden Sie
f = io.open(filename, 'b').
Verwenden Sie zum Öffnen einer Textdatei immer die f = io.open(filename, encoding='utf-8')explizite Codierung.
In Python 3open funktioniert dies jedoch genauso wie io.openund kann stattdessen verwendet werden.
Hinweis: Escodecs.open ist geplant, dass es nach seiner Einführung in Python 2.6 veraltet und ersetzt wird . Ich würde es nur verwenden, wenn Code mit früheren Python-Versionen kompatibel sein muss. Weitere Informationen zu Codecs und Unicode in Python finden Sie im Unicode-HOWTO .io.open
1. Warum kann ich eine Datei im Binärmodus nicht mit io.openoder öffnen codecs.open? 2. codecs.openist noch nicht veraltet, lesen Sie die Diskussion auf der Seite, auf die Sie verlinkt haben.
Wombatonfire
Gute Argumente! 1. Sie können beides verwenden, aber ich würde erneut von codecs.open abraten, es sei denn, Sie verwenden Python 2.5 oder älter. 2. Ich habe meine Antwort aktualisiert, um zu berücksichtigen, dass die Abschreibung nicht sofort, sondern in der Zukunft erfolgte.
wihlke
3
Wenn Sie mit Textdateien arbeiten und eine transparente Codierung und Decodierung in Unicode-Objekte wünschen.
codecs.open()
in 3.x veraltet ist, daopen()
einencoding
Argument gewonnen wird.codecs.open()
veraltet ist? Ich denke nicht, dass dies in Python3-Dokumenten: docs.python.org/3.7/library/codecs.htmlAntworten:
Seit Python 2.6 ist eine gute Praxis zu verwenden
io.open()
, die auch einencoding
Argument wie das jetzt veraltete nimmtcodecs.open()
. In Python 3io.open
ist ein Alias für dasopen()
eingebaute. Funktioniert alsoio.open()
in Python 2.6 und allen späteren Versionen, einschließlich Python 3.4. Siehe Dokumente: http://docs.python.org/3.4/library/io.htmlNun, für die ursprüngliche Frage: beim Lesen Text (einschließlich „Klartext“, HTML, XML und JSON) in Python 2 Sie sollten immer verwenden
io.open()
mit einer expliziten Kodierung oderopen()
mit einer expliziten Kodierung in Python 3. Doing so Mittel erhalten Sie richtig Unicode dekodiert oder sofort einen Fehler angezeigt, was das Debuggen erheblich erleichtert.Reiner ASCII "Klartext" ist ein Mythos aus der fernen Vergangenheit. Der richtige englische Text verwendet geschweifte Anführungszeichen, Striche, Aufzählungszeichen, € (Euro-Zeichen) und sogar Diaeresis (¨). Sei nicht naiv! (Und vergessen wir nicht das Fassadenmuster!)
Da reines ASCII keine echte Option ist, ist
open()
eine explizite Codierung nur zum Lesen von Binärdateien sinnvoll .quelle
io.open()
für Text undopen()
nur für Binärdateien. Die Implikation ist, dass dies überhauptcodecs.open()
nicht bevorzugt wird.open
undcodecs.open
und insbesondere, wann letzteres dem ersteren vorzuziehen ist. Eine Antwort, die nicht einmal erwähnt wird,codecs.open
kann diese Frage nicht beantworten.codecs.open()
die Verwendung korrekt war), gibt es keine "richtige" Antwort darauf, wann sie verwendet werden soll. Die Antwort istio.open()
stattdessen zu verwenden . Es ist wie wenn ich frage "Wann sollte ich einen Schraubenschlüssel verwenden, um einen Nagel in eine Wand zu schlagen?". Die richtige Antwort lautet "Hammer benutzen".Persönlich benutze ich immer , es
codecs.open
sei denn, es gibt einen klar identifizierten Bedarfopen
**. Der Grund ist, dass ich so oft gebissen wurde, weil sich utf-8-Eingaben in meine Programme eingeschlichen haben. "Oh, ich weiß nur, dass es immer ASCII sein wird" ist eine Annahme, die oft gebrochen wird.Die Annahme von 'utf-8' als Standardcodierung ist meiner Erfahrung nach eine sicherere Standardauswahl, da ASCII als UTF-8 behandelt werden kann, aber das Gegenteil ist nicht der Fall. Und in jenen Fällen, in denen ich wirklich weiß , dass die Eingabe ASCII ist, tue ich dies immer noch,
codecs.open
da ich fest davon überzeugt bin, dass "explizit besser als implizit" ist .** - in Python 2.x, wie der Kommentar zu der Frage in Python 3
open
ersetztcodecs.open
quelle
open
manchmal sehr gut mit den UTF-8-codierten nicht-lateinischen Zeichen des Unicode-Setsio.open
nimmt keinen Kodierungsparameter von dem, was ich in Python 2.7.5 sehen kannio.open
akzeptiertencoding
undnewline
parametrisiert sie jedoch und interpretiert sie wie Python 3. Im Gegensatz zucodecs.open
, eine Datei geöffnet mitio.open
erhöhen wirdTypeError: write() argument 1 must be unicode, not str
auch in Python 2.7 , wenn Sie zu schreiben versuchenstr
(bytes
) zu. Eine mit geöffnete Dateicodecs.open
versucht stattdessen eine implizite Konvertierung inunicode
, was häufig zu verwirrendenUnicodeDecodeError
s führt.In Python 2 gibt es Unicode-Zeichenfolgen und Bytestrings. Wenn Sie nur Bytestrings verwenden, können Sie in eine Datei lesen / schreiben, die mit
open()
ganz gut geöffnet wurde . Immerhin sind die Zeichenfolgen nur Bytes.Das Problem tritt auf, wenn Sie beispielsweise eine Unicode-Zeichenfolge haben und Folgendes tun:
Hier codieren Sie also offensichtlich entweder explizit Ihre Unicode-Zeichenfolge in utf-8 oder Sie verwenden
codecs.open
dies, um dies transparent für Sie zu tun.Wenn Sie immer nur Bytestrings verwenden, gibt es keine Probleme:
Dies ist komplizierter, da beim Verketten einer Unicode- und Bytestring-Zeichenfolge mit dem
+
Operator eine Unicode-Zeichenfolge angezeigt wird . Leicht von diesem gebissen zu werden.codecs.open
Mag auch keine Bytestrings mit Nicht-ASCII-Zeichen, die übergeben werden:Der Ratschlag zu Zeichenfolgen für Eingabe / Ausgabe lautet normalerweise "so früh wie möglich in Unicode konvertieren und so spät wie möglich zurück in Bytestrings". Mit
codecs.open
können Sie Letzteres sehr einfach tun.Achten Sie nur darauf, dass Sie ihm Unicode-Zeichenfolgen und keine Bytestrings geben, die möglicherweise Nicht-ASCII-Zeichen enthalten.
quelle
u''
im ersten Beispiel. Dies bedeutet, dass ich eine Unicode-Zeichenfolge erstellt habe, keinen Bytestring. Dies ist der Unterschied zwischen den beiden Beispielen. Im zweiten Beispiel erstelle ich einen Bytestring und das Schreiben eines davon in eine Datei ist in Ordnung. Eine Unicode-Zeichenfolge ist nicht in Ordnung, wenn Sie Zeichen außerhalb von ASCII verwenden.Wenn Sie eine Datei mit einer bestimmten Codierung öffnen müssen, verwenden Sie das
codecs
Modul.quelle
codecs.open
Ich nehme an, es ist nur ein Überbleibsel aus derPython 2
Zeit, als das eingebaute Open eine viel einfachere Oberfläche und weniger Funktionen hatte. In Python 2 wird füropen
die integrierte Funktion kein Codierungsargument verwendet. Wenn Sie also etwas anderes als den Binärmodus oder die Standardcodierung verwenden möchten, sollte codecs.open verwendet werden.In
Python 2.6
kam das io-Modul zur Hilfe, um die Dinge ein bisschen einfacher zu machen. Nach der offiziellen DokumentationTrotzdem kann ich mir
codecs.open
im aktuellen Szenario nur die Abwärtskompatibilität vorstellen. In allen anderen Szenarien (es sei denn, Sie verwenden Python <2.6) ist die Verwendung vorzuziehenio.open
. Auch inPython 3.x
io.open
ist das gleiche wiebuilt-in open
Hinweis:
Es gibt auch einen syntaktischen Unterschied zwischen
codecs.open
undio.open
.codecs.open
::io.open
::quelle
codecs.open
undio.open
unterscheiden sich in der Syntax, kehren sie Objekte unterschiedlicher Art. Funktioniert auchcodecs.open
immer mit Dateien im Binärmodus.Wenn Sie eine Binärdatei laden möchten, verwenden Sie
f = io.open(filename, 'b')
.Verwenden Sie zum Öffnen einer Textdatei immer die
f = io.open(filename, encoding='utf-8')
explizite Codierung.In Python 3
open
funktioniert dies jedoch genauso wieio.open
und kann stattdessen verwendet werden.quelle
io.open
oder öffnencodecs.open
? 2.codecs.open
ist noch nicht veraltet, lesen Sie die Diskussion auf der Seite, auf die Sie verlinkt haben.Wenn Sie mit Textdateien arbeiten und eine transparente Codierung und Decodierung in Unicode-Objekte wünschen.
quelle
Ich war in der Lage, eine .asm-Datei zu öffnen und die Datei zu verarbeiten.
Ohne viel Mühe kann ich die gesamte Datei lesen, irgendwelche Vorschläge?
quelle