Есть два способа открыть текстовый файл в Python:
f = open(filename)
А также
import codecs
f = codecs.open(filename, encoding="utf-8")
Когда codecs.open
предпочтительнее open
?
Есть два способа открыть текстовый файл в Python:
f = open(filename)
А также
import codecs
f = codecs.open(filename, encoding="utf-8")
Когда codecs.open
предпочтительнее open
?
codecs.open()
устаревшие ссылки ? Я не думаю , что это в Python3 документы: docs.python.org/3.7/library/codecs.html
Ответы:
Начиная с 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()
без явного кодирования полезно только читать двоичные файлы.
io.open()
для текста и open()
только для двоичных файлов . Подразумевается, что codecs.open()
это вообще нежелательно.
open
codecs.open
codecs.open
codecs.open()
его правильно использовать), тогда нет «правильного» ответа о том, когда его использовать. Ответ - использовать io.open()
вместо этого. Это как если бы я спросил: «Когда я должен использовать гаечный ключ, чтобы вбить гвоздь в стену?». Правильный ответ - «используйте молоток».
Лично я всегда использую, codecs.open
если нет четко определенной потребности в использовании open
**. Причина в том, что очень много раз меня кусало, что входные данные utf-8 проникают в мои программы. «О, я просто знаю, что это всегда будет ascii» - это предположение, которое часто нарушается.
По моему опыту, использование utf-8 в качестве кодировки по умолчанию имеет тенденцию быть более безопасным выбором по умолчанию, поскольку ASCII можно рассматривать как UTF-8, но обратное неверно. И в тех случаях, когда я действительно знаю, что ввод - это ASCII, я все еще делаю это, codecs.open
поскольку твердо верю в «явное лучше, чем неявное» .
** - в Python 2.x, поскольку комментарий к вопросу в Python 3 open
заменяетcodecs.open
open
иногда может очень хорошо обрабатывать нелатинские символы в кодировке UTF-8 из набора Unicode, а иногда он терпит неудачу ...
io.open
не принимает параметр кодировки из того, что я вижу в python 2.7.5
io.open
принимает encoding
и newline
параметры и интерпретирует их как Python 3 делает. В отличие от этого codecs.open
, файл, открытый с помощью, io.open
будет подниматься TypeError: write() argument 1 must be unicode, not str
даже в Python 2.7, если вы попытаетесь написать в него str
( bytes
). Файл, открытый с помощью codecs.open
, вместо этого будет пытаться неявно преобразовать в unicode
, что часто приводит к путанице UnicodeDecodeError
.
В Python 2 есть строки Unicode и байтовые строки. Если вы просто используете байтовые строки, вы можете читать / писать в файл, открытый без проблем 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 и строку байтов с +
оператором, вы получаете строку 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)
Совет относительно строк для ввода / вывода обычно таков: «преобразовать в Unicode как можно раньше, а обратно в байтовые строки как можно позже». Использование codecs.open
позволяет очень легко сделать последнее.
Просто будьте осторожны, дайте ему строки Unicode, а не строки байтов, которые могут содержать символы, отличные от ASCII.
u''
в первом примере. Это означает, что я создал строку юникода, а не строку байтов. В этом разница между двумя примерами. Во втором примере я создаю байтовую строку, и записать одну из них в файл вполне нормально. Строка Unicode не подходит, если вы используете символы вне ASCII.
codecs.open
Я полагаю, это всего лишь пережиток тех Python 2
дней, когда встроенный open имел гораздо более простой интерфейс и меньше возможностей. В Python 2 встроенный open
не принимает аргумент кодировки, поэтому, если вы хотите использовать что-то другое, кроме двоичного режима или кодировки по умолчанию, предполагалось использовать codecs.open.
В In 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)
codecs.open
и io.open
различаются с точки зрения синтаксиса, они возвращают объекты различного типа. Также codecs.open
всегда работает с файлами в двоичном режиме.
Если вы хотите загрузить двоичный файл, используйте
f = io.open(filename, 'b')
.
Для открытия текстового файла всегда используйте f = io.open(filename, encoding='utf-8')
явную кодировку.
В Python 3 , однако open
делает то же самое, что io.open
и может быть использован вместо.
Примечание.
codecs.open
Планируется, что после его появления в Python 2.6 он станет устаревшим и будет заменен на . Я бы использовал его только в том случае, если код должен быть совместим с более ранними версиями python. Для получения дополнительной информации о кодеках и Unicode в Python см. Unicode HOWTO .io.open
io.open
или codecs.open
? 2. codecs.open
еще не устарел, прочтите обсуждение на странице, на которую вы ссылаетесь.
Когда вы работаете с текстовыми файлами и хотите прозрачное кодирование и декодирование в объекты 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:
Без особых проблем я могу прочитать весь файл, есть предложения?
codecs.open()
это устарело в 3.x, так какopen()
получаетencoding
аргумент.