Il existe deux façons d'ouvrir un fichier texte en Python:
f = open(filename)
Et
import codecs
f = codecs.open(filename, encoding="utf-8")
Quand est-il codecs.open
préférable open
?
Il existe deux façons d'ouvrir un fichier texte en Python:
f = open(filename)
Et
import codecs
f = codecs.open(filename, encoding="utf-8")
Quand est-il codecs.open
préférable open
?
codecs.open()
obsolète? Je ne pense pas que cela dans les documents python3: docs.python.org/3.7/library/codecs.html
Réponses:
Depuis Python 2.6, une bonne pratique consiste à utiliser io.open()
, qui prend également un encoding
argument, comme le maintenant obsolète codecs.open()
. Dans Python 3, io.open
est 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.
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é.
open
et 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.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 à 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".
Personnellement, je toujours utiliser codecs.open
moins 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.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
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 échoue
io.open
ne prend pas de paramètre d'encodage de ce que je peux voir en python 2.7.5
io.open
accepte encoding
et newline
paramètres et les interprète comme le fait Python 3. Contrairement à codecs.open
, un fichier ouvert avec io.open
se lèvera TypeError: write() argument 1 must be unicode, not str
même en Python 2.7 si vous essayez d'écrire str
( bytes
) dessus. Un fichier ouvert avec codecs.open
tentera à la place une conversion implicite en unicode
, conduisant souvent à la confusion UnicodeDecodeError
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:
>>> 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.open
pour 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.open
ne 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.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.
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.
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 officielle
New in version 2.6.
The io module provides the Python interfaces to stream handling.
Under Python 2.x, this is proposed as an alternative to the
built-in file object, but in Python 3.x it is the default
interface to access files and streams.
Cela 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'utiliser io.open
. Est également Python 3.x
io.open
le même quebuilt-in open
Remarque:
Il existe également une différence syntaxique entre codecs.open
et io.open
.
codecs.open
:
open(filename, mode='rb', encoding=None, errors='strict', buffering=1)
io.open
:
open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)
codecs.open
et io.open
diffèrent en termes de syntaxe, ils renvoient des objets de type différent. Fonctionne également codecs.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 chose io.open
et peut être utilisé à la place.
Remarque:
codecs.open
est prévu de devenir obsolète et remplacé pario.open
aprè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 .
io.open
ou codecs.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.
J'étais dans une situation pour ouvrir un fichier .asm et traiter le fichier.
#https://docs.python.org/3/library/codecs.html#codecs.ignore_errors
#https://docs.python.org/3/library/codecs.html#codecs.Codec.encode
with codecs.open(file, encoding='cp1252', errors ='replace') as file:
Sans trop de problèmes, je suis capable de lire l'intégralité du fichier, des suggestions?
codecs.open()
c'est obsolète dans 3.x, caropen()
gagne unencoding
argument.