Існує два способи відкрити текстовий файл у 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()взагалі не бажано.
opencodecs.opencodecs.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.openwill, замість цього робить спробу неявного перетворення unicode, часто приводячи до плутанини UnicodeDecodeErrors.
У 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аргумент.