Разница между открытым и codecs.open в Python - PullRequest
76 голосов
/ 09 марта 2011

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

f = open(filename)

И

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

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

Ответы [ 7 ]

73 голосов
/ 10 марта 2014

Начиная с 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

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

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

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

18 голосов
/ 01 ноября 2012

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

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

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

8 голосов
/ 12 ноября 2013

В Python 2 есть строки в юникоде и строки байтов. Если вы просто используете строки байтов, вы можете читать / записывать в файл, открытый с 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)

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

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

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

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

Также 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.

6 голосов
/ 09 марта 2011

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

5 голосов
/ 12 декабря 2018

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) предпочтительно использовать <code>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)
3 голосов
/ 09 марта 2011

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

2 голосов
/ 12 сентября 2018
  • Если вы хотите загрузить двоичный файл, используйте 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 .

...