Разница между open и codecs.open в Python

Существует два способа открыть текстовый файл в Python:

f = open(filename)

и

import codecs
f = codecs.open(filename, encoding="utf-8")

Когда codecs.open предпочтительнее open?

Ответ 1

С Python 2.6 хорошей практикой является использование io.open(), который также принимает аргумент encoding, например, теперь устаревший codecs.open(). В Python 3, io.open является псевдонимом для встроенного open(). Итак, io.open() работает в Python 2.6 и всех последующих версиях, включая Python 3.4. См. Документы: http://docs.python.org/3.4/library/io.html

Теперь, для исходного вопроса: при чтении текста (включая "обычный текст", HTML, XML и JSON) в Python 2 вы должны всегда использовать io.open() с явным кодированием или open() с явным кодированием в Python 3. Это значит, что вы правильно декодировали Unicode или получаете ошибку сразу с места в карьер, что облегчает отладку.

Чистый ASCII "простой текст" - это миф из далекого прошлого. Правильный английский текст использует фигурные кавычки, em-тире, маркеры, евро (знаки евро) и даже диарезис (¨). Не будь наивным! (И не забывайте о шаблоне дизайна фасада!)

Поскольку чистый ASCII не является реальным вариантом, open() без явного кодирования только полезно читать двоичные файлы.

Ответ 2

Лично я всегда использую codecs.open, если нет четко определенной необходимости использовать open **. Причина в том, что было так много раз, когда меня укусили, когда входные данные utf-8 проникали в мои программы. "О, я просто знаю, что это всегда будет ascii", как правило, является предположением, которое часто ломается.

Предполагая, что "utf-8", поскольку кодировка по умолчанию имеет тенденцию быть более безопасным выбором по умолчанию в моем опыте, поскольку ASCII можно рассматривать как UTF-8, но обратное неверно. И в тех случаях, когда я действительно знаю, что вход ASCII, я все еще делаю codecs.open, поскольку я твердо верю в "Явный лучше, чем неявный" .

** - в Python 2.x, поскольку комментарий к вопросу в Python 3 open заменяет codecs.open

Ответ 3

В Python 2 есть строки unicode и bytestrings. Если вы просто используете bytestrings, вы можете читать/записывать в файл, открытый с помощью open(), просто отлично. В конце концов, строки - это просто байты.

Проблема возникает, когда, скажем, у вас есть строка в Юникоде, и вы делаете следующее:

>>> 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)

Итак, очевидно, что вы либо явно кодируете строку unicode в utf-8, либо используете codecs.open, чтобы сделать это для вас прозрачно.

Если вы только когда-либо используете bytestrings, тогда никаких проблем:

>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>

Он становится более привлекательным, чем это, потому что когда вы объединяете строку unicode и bytestring с помощью оператора +, вы получаете строку юникода. Легко укусить его.

Также codecs.open не любит байты с передачей символов, отличных от ASCII:

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)

Совет о строках ввода/вывода обычно "конвертируется в Юникод как можно раньше и обратно к байтам как можно позже". Использование codecs.open позволяет сделать последнее очень легко.

Просто будьте осторожны, вы указываете строки unicode, а не теги, которые могут иметь символы, отличные от ASCII.

Ответ 4

Когда вам нужно открыть файл с определенной кодировкой, вы должны использовать модуль codecs.

Ответ 5

codecs.open, codecs.open - это всего лишь остаток от Python 2 codecs.open Python 2 дня, когда встроенный открытый интерфейс имел гораздо более простой интерфейс и меньше возможностей. В Python 2 встроенный open не принимает аргумент кодировки, поэтому, если вы хотите использовать что-то отличное от двоичного режима или кодировки по умолчанию, должен был использоваться codecs.open.

В Python 2.6 модуль io пришел на помощь, чтобы сделать вещи немного проще. Согласно официальной документации

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.

Сказав это, единственное использование, которое я могу придумать для codecs.open в текущем сценарии, - это обратная совместимость. Во всех других сценариях (если вы не используете Python <2.6) предпочтительно использовать io.open. Также в Python 3.x io.open такой же, как built-in open

Замечания:

Существует также синтаксическая разница между codecs.open и 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)

Ответ 6

Когда вы работаете с текстовыми файлами и хотите прозрачную кодировку и декодирование в объекты Unicode.

Ответ 7

  • Если вы хотите загрузить двоичный файл, используйте f = io.open(filename, 'b').

  • Для открытия текстового файла всегда используйте f = io.open(filename, encoding='utf-8') с явной кодировкой.

Однако в python 3 open делает то же самое, что и io.open и может использоваться вместо него.

Примечание: codecs.open планируется стать устаревшим и заменен io.open после его введения в Python 2.6. Я бы использовал его, только если код должен быть совместим с более ранними версиями Python. Для получения дополнительной информации о кодеках и Unicode в Python см. Unicode HOWTO.