web-dev-qa-db-fra.com

Différence entre open et codecs.open dans Python

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?

77
BlogueroConnor

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 .

73
Luciano Ramalho

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

18
Adam Parkin

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.

8
Mandible79

Lorsque vous devez ouvrir un fichier ayant un certain encodage, vous utilisez le module codecs.

6
Geo

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.xio.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)
5
heretolearn

Lorsque vous travaillez avec des fichiers texte et que vous souhaitez un encodage et un décodage transparents en objets Unicode.

3
Cat Plus Plus
  • 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é par io.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 .

2
wihlke