Існує два способи відкрити текстовий файл у 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: 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, як open
замінено коментарем до питання в Python 3codecs.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
will, замість цього робить спробу неявного перетворення unicode
, часто приводячи до плутанини UnicodeDecodeError
s.
У Python 2 є рядки Unicode і bytestring. Якщо ви просто використовуєте bytestring, ви можете читати / писати у файл, відкритий 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
щоб зробити це для вас прозоро.
Якщо ви тільки коли-небудь використовуєте bytestrings, то проблем немає:
>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>
Він залучається більше, ніж це, тому що, коли ви об'єднуєте рядок unicode та bytestring з +
оператором, ви отримуєте рядок unicode. Його легко вкусити.
Також codecs.open
не подобається bytestring з символами, що не належать до 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 якомога раніше і повертати в bytestring якомога пізніше". Використання codecs.open
дозволяє зробити останнє дуже легко.
Тільки будьте обережні, що ви надаєте йому рядки Unicode, а не bytestring, які можуть мати символи, що не є ASCII.
u''
в першому прикладі. Це означає, що я створив рядок юнікоду, а не байтовий рядок. У цьому різниця між двома прикладами. У другому прикладі я створюю тестування байтів і виписую одне з них у файл - це чудово. Рядок Unicode не є нормальним, якщо ви використовуєте символи поза 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.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
планується застаріти та замінитиio.open
після введення в python 2.6 . Я б використовував його, лише якщо код повинен бути сумісним з попередніми версіями python. Для отримання додаткової інформації про кодеки та unicode в python див. Unicode HOWTO .
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
аргумент.