Разница между открытым и codecs.open в Python

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

f = open(filename)

А также

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

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

6 ответов

Начиная с 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 "простой текст" - это миф из далекого прошлого. Надлежащий английский текст использует фигурные кавычки, тире, маркеры, евро (знаки евро) и даже диарез (¨). Не будь наивным! (И давайте не будем забывать шаблон дизайна Фасада!)

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

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

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

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

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

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

>>> 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 сделать это для вас прозрачно.

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

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

Это становится более сложным, чем это, потому что когда вы объединяете юникод и строку байтовой строки с + Оператор, вы получите строку Unicode. Легко быть укушенным этим.

Также 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 позволяет сделать последнее очень легко.

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

codecs.openПолагаю, это всего лишь остаток от Python 2 дни, когда встроенный open имел гораздо более простой интерфейс и меньше возможностей. В 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.xio.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)

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

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

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

В питоне 3 однако open(filename, encoding='utf-8') делает то же самое и может быть использован вместо.

Замечания: codecs.open в настоящее время устарела и заменена io.open после его введения в Python 2.6. Для получения дополнительной информации о кодеках и Unicode в Python см. Unicode HOWTO.

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

Я был в ситуации, чтобы открыть файл.asm и обработать его.

#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:

Без особых проблем я могу прочитать весь файл, есть предложения?

Другие вопросы по тегам