Notez que codecs.open()c'est obsolète dans 3.x, car open()gagne un encodingargument.
Ignacio Vazquez-Abrams
Il y a aussi une troisième méthode (en Python 2.x au moins): `f = file (filename) '
Adam Parkin
1
@ IgnacioVazquez-Abrams Existe-t-il un lien codecs.open()obsolète? Je ne pense pas que cela dans les documents python3: docs.python.org/3.7/library/codecs.html
varela
1
@varela: la page de documentation Python que vous avez mentionnée dit: "l'open () intégré et le module io associé sont l'approche recommandée pour travailler avec des fichiers texte encodés"
Luciano Ramalho
Réponses:
82
Depuis Python 2.6, une bonne pratique consiste à utiliser io.open(), qui prend également un encodingargument, comme le maintenant obsolète codecs.open(). Dans Python 3, io.openest un alias pour le open()fichier intégré. Fonctionne donc io.open()avec Python 2.6 et toutes les versions ultérieures, y compris Python 3.4. Voir la documentation: http://docs.python.org/3.4/library/io.html
Maintenant, pour la question d'origine: lors de la lecture de texte (y compris "texte brut", HTML, XML et JSON) en Python 2, vous devez toujours l' utiliser io.open()avec un encodage explicite, ou open()avec un encodage explicite en Python 3. Cela signifie que vous obtenez correctement décodé Unicode, ou obtenir une erreur dès le départ, ce qui facilite grandement le débogage.
Le «texte brut» ASCII pur est un mythe d'un passé lointain. Un texte anglais correct utilise des guillemets bouclés, des tirets em, des puces, des € (signes de l'euro) et même des tracés (¨). Ne soyez pas naïf! (Et n'oublions pas le modèle de conception Façade!)
Parce que ASCII pur est pas une option réelle, open()sans un codage explicite est seulement utile pour lire binaires fichiers.
@ForeverWintr La réponse est assez claire là-dedans: utiliser io.open()pour le texte, et open()uniquement pour le binaire. L'implication est que ce codecs.open()n'est pas du tout préféré.
Bdoserror
2
@Bdoserror, Il y a une réponse là-dedans, clairement, mais ce n'est pas une réponse à la question qui a été posée. La question portait sur la différence entre openet codecs.open, et plus précisément quand ce dernier est préférable au premier. Une réponse qui ne fait pas autant que mentionner codecs.openne peut pas répondre à cette question.
ForeverWintr
3
@ForeverWintr Si l'OP a posé la mauvaise question (c'est-à-dire avec l'hypothèse qu'il codecs.open()était correct d'utiliser), alors il n'y a pas de réponse "correcte" sur le moment de l'utiliser. La réponse est d'utiliser à la io.open()place. C'est comme si je demandais "quand dois-je utiliser une clé pour enfoncer un clou dans un mur?". La bonne réponse est "utiliser un marteau".
Bdoserror
20
Personnellement, je toujours utiliser codecs.openmoins qu'il y ait un besoin identifié clairement à l' utilisation open**. La raison en est qu'il y a eu tellement de fois où j'ai été mordu en ayant une entrée utf-8 se faufiler dans mes programmes. "Oh, je sais juste que ce sera toujours ascii" a tendance à être une hypothèse qui est souvent rompue.
En supposant 'utf-8' comme encodage par défaut, cela a tendance à être un choix par défaut plus sûr selon mon expérience, car ASCII peut être traité comme UTF-8, mais l'inverse n'est pas vrai. Et dans ces cas où je sais vraiment que l'entrée est ASCII, alors je fais toujours codecs.opencomme je suis un fervent partisan de "l'explicite vaut mieux que l'implicite" .
** - en Python 2.x, car le commentaire sur la question indique dans Python 3 openremplacecodecs.open
ce que je ne comprends pas vraiment, c'est pourquoi je openpeux parfois très bien gérer les caractères non latins encodés en UTF-8 de l'ensemble unicode, et parfois cela échoue
misérablement
Cela a du sens pour moi. io.openne prend pas de paramètre d'encodage de ce que je peux voir en python 2.7.5
radtek
1
@radtek, vous avez raison de dire que ce n'est pas documenté; cependant (au moins en 2.7.12) io.openaccepte encodinget newlineparamètres et les interprète comme le fait Python 3. Contrairement à codecs.open, un fichier ouvert avec io.opense lèvera TypeError: write() argument 1 must be unicode, not strmême en Python 2.7 si vous essayez d'écrire str( bytes) dessus. Un fichier ouvert avec codecs.opententera à la place une conversion implicite en unicode, conduisant souvent à la confusion UnicodeDecodeErrors.
jochietoch
9
Dans Python 2, il existe des chaînes et des chaînes d'octets Unicode. Si vous utilisez simplement des chaînes d'octets, vous pouvez lire / écrire dans un fichier ouvert avec open()très bien. Après tout, les chaînes ne sont que des octets.
Le problème survient lorsque, par exemple, vous avez une chaîne Unicode et que vous procédez comme suit:
>>> 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)
Donc ici, évidemment, vous encodez explicitement votre chaîne unicode en utf-8 ou vous l'utilisez codecs.openpour le faire pour vous de manière transparente.
Si vous n'utilisez que des bytestrings, aucun problème:
>>> example ='Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)>>>
Cela devient plus compliqué que cela car lorsque vous concaténez une chaîne Unicode et une chaîne d'octets avec l' +opérateur, vous obtenez une chaîne Unicode. Facile de se faire mordre par celui-là.
Aussi codecs.openne fonctionne pas comme avec les chaînes d' octets non ASCII caractères sont transmis dans:
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)
Le conseil concernant les chaînes d'entrée / sortie est normalement de "convertir en Unicode le plus tôt possible et de revenir aux chaînes d'octets le plus tard possible". L'utilisation codecs.openvous permet de faire ce dernier très facilement.
Veillez simplement à lui donner des chaînes Unicode et non des chaînes d'octets pouvant contenir des caractères non ASCII.
Pouvez-vous expliquer votre deuxième exemple? Il semble être identique à votre premier exemple, alors pourquoi le résultat serait-il différent?
Chris Johnson
Notez l'utilisation du u''dans le premier exemple. Cela signifie que j'ai créé une chaîne Unicode, pas une chaîne d'octets. C'est la différence entre les deux exemples. Dans le deuxième exemple, je crée une chaîne d'octets et j'en écris un dans un fichier est très bien. Une chaîne Unicode ne convient pas si vous utilisez des caractères en dehors de ASCII.
Mandible79
7
Lorsque vous avez besoin d'ouvrir un fichier qui a un certain codage, vous utiliserez le codecsmodule.
Je suppose que tous les fichiers texte ont un certain encodage, en quelque sorte (:
cedbeu
5
codecs.open, je suppose, n'est qu'un vestige de l' Python 2époque où l'open intégré avait une interface beaucoup plus simple et moins de capacités. Dans Python 2, intégré openne prend pas d'argument d'encodage, donc si vous voulez utiliser autre chose que le mode binaire ou l'encodage par défaut, codecs.open était censé être utilisé.
Dans Python 2.6, le module io est venu en aide pour rendre les choses un peu plus simples. Selon la documentation officielle
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.
Cela dit, la seule utilisation à laquelle je peux penser codecs.opendans le scénario actuel est la compatibilité descendante. Dans tous les autres scénarios (sauf si vous utilisez Python <2.6), il est préférable d'utiliser io.open. Est également Python 3.xio.openle même quebuilt-in open
Remarque:
Il existe également une différence syntaxique entre codecs.openet io.open.
Non seulement codecs.openet io.opendiffèrent en termes de syntaxe, ils renvoient des objets de type différent. Fonctionne également codecs.opentoujours avec des fichiers en mode binaire.
wombatonfire
4
Lorsque vous souhaitez charger un fichier binaire, utilisez
f = io.open(filename, 'b').
Pour ouvrir un fichier texte, utilisez toujours f = io.open(filename, encoding='utf-8')un encodage explicite.
En python 3 fait cependant openla même chose io.openet peut être utilisé à la place.
Remarque:codecs.open est prévu de devenir obsolète et remplacé par io.openaprès son introduction dans python 2.6 . Je ne l'utiliserais que si le code doit être compatible avec les versions antérieures de python. Pour plus d'informations sur les codecs et l'unicode en python, consultez le HOWTO Unicode .
1. Pourquoi ne puis-je pas ouvrir un fichier en mode binaire avec io.openou codecs.open? 2. codecs.openn'est pas encore obsolète, lisez la discussion sur la page à laquelle vous avez lié.
wombatonfire
Bons points! 1. Vous pouvez utiliser l'un ou l'autre, mais je conseillerais à nouveau contre codecs.open à moins que vous ne soyez sur python 2.5 ou plus ancien. 2. J'ai mis à jour ma réponse pour indiquer que la dépréciation n'a pas eu lieu immédiatement, mais plutôt à l'avenir.
wihlke
3
Lorsque vous travaillez avec des fichiers texte et que vous souhaitez un encodage et un décodage transparents en objets Unicode.
codecs.open()
c'est obsolète dans 3.x, caropen()
gagne unencoding
argument.codecs.open()
obsolète? Je ne pense pas que cela dans les documents python3: docs.python.org/3.7/library/codecs.htmlRéponses:
Depuis Python 2.6, une bonne pratique consiste à utiliser
io.open()
, qui prend également unencoding
argument, comme le maintenant obsolètecodecs.open()
. Dans Python 3,io.open
est un alias pour leopen()
fichier intégré. Fonctionne doncio.open()
avec Python 2.6 et toutes les versions ultérieures, y compris Python 3.4. Voir la documentation: http://docs.python.org/3.4/library/io.htmlMaintenant, pour la question d'origine: lors de la lecture de texte (y compris "texte brut", HTML, XML et JSON) en Python 2, vous devez toujours l' utiliser
io.open()
avec un encodage explicite, ouopen()
avec un encodage explicite en Python 3. Cela signifie que vous obtenez correctement décodé Unicode, ou obtenir une erreur dès le départ, ce qui facilite grandement le débogage.Le «texte brut» ASCII pur est un mythe d'un passé lointain. Un texte anglais correct utilise des guillemets bouclés, des tirets em, des puces, des € (signes de l'euro) et même des tracés (¨). Ne soyez pas naïf! (Et n'oublions pas le modèle de conception Façade!)
Parce que ASCII pur est pas une option réelle,
open()
sans un codage explicite est seulement utile pour lire binaires fichiers.la source
io.open()
pour le texte, etopen()
uniquement pour le binaire. L'implication est que cecodecs.open()
n'est pas du tout préféré.open
etcodecs.open
, et plus précisément quand ce dernier est préférable au premier. Une réponse qui ne fait pas autant que mentionnercodecs.open
ne peut pas répondre à cette question.codecs.open()
était correct d'utiliser), alors il n'y a pas de réponse "correcte" sur le moment de l'utiliser. La réponse est d'utiliser à laio.open()
place. C'est comme si je demandais "quand dois-je utiliser une clé pour enfoncer un clou dans un mur?". La bonne réponse est "utiliser un marteau".Personnellement, je toujours utiliser
codecs.open
moins qu'il y ait un besoin identifié clairement à l' utilisationopen
**. La raison en est qu'il y a eu tellement de fois où j'ai été mordu en ayant une entrée utf-8 se faufiler dans mes programmes. "Oh, je sais juste que ce sera toujours ascii" a tendance à être une hypothèse qui est souvent rompue.En supposant 'utf-8' comme encodage par défaut, cela a tendance à être un choix par défaut plus sûr selon mon expérience, car ASCII peut être traité comme UTF-8, mais l'inverse n'est pas vrai. Et dans ces cas où je sais vraiment que l'entrée est ASCII, alors je fais toujours
codecs.open
comme je suis un fervent partisan de "l'explicite vaut mieux que l'implicite" .** - en Python 2.x, car le commentaire sur la question indique dans Python 3
open
remplacecodecs.open
la source
open
peux parfois très bien gérer les caractères non latins encodés en UTF-8 de l'ensemble unicode, et parfois cela échoueio.open
ne prend pas de paramètre d'encodage de ce que je peux voir en python 2.7.5io.open
accepteencoding
etnewline
paramètres et les interprète comme le fait Python 3. Contrairement àcodecs.open
, un fichier ouvert avecio.open
se lèveraTypeError: write() argument 1 must be unicode, not str
même en Python 2.7 si vous essayez d'écrirestr
(bytes
) dessus. Un fichier ouvert aveccodecs.open
tentera à la place une conversion implicite enunicode
, conduisant souvent à la confusionUnicodeDecodeError
s.Dans Python 2, il existe des chaînes et des chaînes d'octets Unicode. Si vous utilisez simplement des chaînes d'octets, vous pouvez lire / écrire dans un fichier ouvert avec
open()
très bien. Après tout, les chaînes ne sont que des octets.Le problème survient lorsque, par exemple, vous avez une chaîne Unicode et que vous procédez comme suit:
Donc ici, évidemment, vous encodez explicitement votre chaîne unicode en utf-8 ou vous l'utilisez
codecs.open
pour le faire pour vous de manière transparente.Si vous n'utilisez que des bytestrings, aucun problème:
Cela devient plus compliqué que cela car lorsque vous concaténez une chaîne Unicode et une chaîne d'octets avec l'
+
opérateur, vous obtenez une chaîne Unicode. Facile de se faire mordre par celui-là.Aussi
codecs.open
ne fonctionne pas comme avec les chaînes d' octets non ASCII caractères sont transmis dans:Le conseil concernant les chaînes d'entrée / sortie est normalement de "convertir en Unicode le plus tôt possible et de revenir aux chaînes d'octets le plus tard possible". L'utilisation
codecs.open
vous permet de faire ce dernier très facilement.Veillez simplement à lui donner des chaînes Unicode et non des chaînes d'octets pouvant contenir des caractères non ASCII.
la source
u''
dans le premier exemple. Cela signifie que j'ai créé une chaîne Unicode, pas une chaîne d'octets. C'est la différence entre les deux exemples. Dans le deuxième exemple, je crée une chaîne d'octets et j'en écris un dans un fichier est très bien. Une chaîne Unicode ne convient pas si vous utilisez des caractères en dehors de ASCII.Lorsque vous avez besoin d'ouvrir un fichier qui a un certain codage, vous utiliserez le
codecs
module.la source
codecs.open
, je suppose, n'est qu'un vestige de l'Python 2
époque où l'open intégré avait une interface beaucoup plus simple et moins de capacités. Dans Python 2, intégréopen
ne prend pas d'argument d'encodage, donc si vous voulez utiliser autre chose que le mode binaire ou l'encodage par défaut, codecs.open était censé être utilisé.Dans
Python 2.6
, le module io est venu en aide pour rendre les choses un peu plus simples. Selon la documentation officielleCela dit, la seule utilisation à laquelle je peux penser
codecs.open
dans le scénario actuel est la compatibilité descendante. Dans tous les autres scénarios (sauf si vous utilisez Python <2.6), il est préférable d'utiliserio.open
. Est égalementPython 3.x
io.open
le même quebuilt-in open
Remarque:
Il existe également une différence syntaxique entre
codecs.open
etio.open
.codecs.open
:io.open
:la source
codecs.open
etio.open
diffèrent en termes de syntaxe, ils renvoient des objets de type différent. Fonctionne égalementcodecs.open
toujours avec des fichiers en mode binaire.Lorsque vous souhaitez charger un fichier binaire, utilisez
f = io.open(filename, 'b')
.Pour ouvrir un fichier texte, utilisez toujours
f = io.open(filename, encoding='utf-8')
un encodage explicite.En python 3 fait cependant
open
la même choseio.open
et peut être utilisé à la place.la source
io.open
oucodecs.open
? 2.codecs.open
n'est pas encore obsolète, lisez la discussion sur la page à laquelle vous avez lié.Lorsque vous travaillez avec des fichiers texte et que vous souhaitez un encodage et un décodage transparents en objets Unicode.
la source
J'étais dans une situation pour ouvrir un fichier .asm et traiter le fichier.
Sans trop de problèmes, je suis capable de lire l'intégralité du fichier, des suggestions?
la source