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 codecs.open
préférable à open
?
Depuis Python 2.6, une bonne pratique consiste à utiliser io.open()
, qui prend également un argument encoding
, comme le désormais obsolète codecs.open()
. Dans Python 3, io.open
Est un alias pour le open()
intégré. io.open()
fonctionne donc dans Python 2.6 et toutes les versions ultérieures, y compris Python 3.4. Voir les documents: http://docs.python.org/3.4/library/io.html
Maintenant, pour la question d'origine: lorsque vous lisez texte (y compris "texte brut", HTML, XML et JSON) dans Python 2 vous devez toujours utilisez io.open()
avec un encodage explicite, ou open()
avec un encodage explicite dans Python 3. Cela signifie que vous obtenez Unicode correctement décodé, ou obtenez une erreur correcte au départ, ce qui facilite le débogage.
Pure ASCII "texte brut" est un mythe d'un passé lointain. Un texte anglais correct utilise des guillemets bouclés, des tirets em, des puces, des € (signes euro) et même des tréma (¨). Ne sois pas naïf! (Et n'oublions pas le motif de conception de la façade!)
Parce que pur ASCII n'est pas une vraie option, open()
sans encodage explicite est seulement utile pour lire binaire fichiers .
Personnellement, j'utilise toujours codecs.open
sauf s'il existe un besoin clairement identifié d'utiliser 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 dans mes programmes. "Oh, je sais juste que ce sera toujours ascii" a tendance à être une hypothèse qui se brise souvent.
En supposant que "utf-8" comme codage par défaut a tendance à être un choix par défaut plus sûr dans mon expérience, puisque ASCII peut être traité comme UTF-8, mais l'inverse n'est pas vrai. cas où je sais vraiment savoir que l'entrée est ASCII, alors je continue codecs.open
car je crois fermement en "explicite vaut mieux qu'implicite" .
** - dans Python 2.x, comme l'indique le commentaire sur la question dans Python 3 open
remplace codecs.open
Dans Python 2 il y a des chaînes et des bytestrings Unicode. Si vous utilisez simplement des bytestrings, vous pouvez très bien lire/écrire dans un fichier ouvert avec open()
. 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 dans utf-8 ou vous utilisez codecs.open
pour le faire en toute transparence.
Si vous n'utilisez que des bytestrings, aucun problème:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
Cela devient plus compliqué que cela parce que lorsque vous concaténez une chaîne unicode et bytestring avec le +
opérateur vous obtenez une chaîne unicode. Facile à se faire mordre par celui-là.
Également codecs.open
n'aime pas les bytestrings avec des caractères non ASCII transmis:
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 sur les chaînes d'entrée/sortie est normalement "convertir en unicode le plus tôt possible et revenir aux bytestrings le plus tard possible". En utilisant codecs.open
vous permet de faire ce dernier très facilement.
Faites juste attention de lui donner des chaînes unicode et non des bytestrings qui peuvent avoir des caractères non ASCII.
Lorsque vous devez ouvrir un fichier ayant un certain encodage, vous utilisez le module codecs
.
codecs.open
, je suppose, n'est qu'un vestige du Python 2
jours où l'ouverture intégrée avait une interface beaucoup plus simple et moins de capacités. Dans Python 2, le open
intégré ne prend pas d'argument de codage, donc si vous voulez utiliser autre chose que le mode binaire ou le codage par défaut, codecs.open était censé être utilisé.
Dans Python 2.6
, le module io est venu à l'aide pour simplifier les choses. Selon le fonctionnaire documentation
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 pour 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
. Aussi dans Python 3.x
io.open
est le même que built-in open
Remarque:
Il existe une différence syntaxique entre codecs.open
et io.open
ainsi que.
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)
Lorsque vous travaillez avec des fichiers texte et que vous souhaitez un encodage et un décodage transparents en objets Unicode.
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')
avec un codage explicite.
En python 3 cependant open
fait la même chose que io.open
et peut être utilisé à la place.
Remarque:
codecs.open
devrait 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 dans python voir le nicode) HOWTO .