Документация Python неофициальный перевод

csv.md

367 строк · 33.4 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.5/library/csv.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 14.1. [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) – чтение и запись CSV-файлов89**Исходный код:** [Lib/csv.py](https://python-all.ru/src/3.5/Lib/csv.py)1011---1213Так называемый формат CSV (Comma Separated Values) – самый распространенный формат импорта и экспорта для электронных таблиц и баз данных. Формат CSV использовался много лет до попыток дать ему стандартизированное описание в [**RFC 4180**](https://python-all.ru/3.5/library/csv.html). Отсутствие четкого стандарта приводит к тому, что в данных, создаваемых и используемых разными приложениями, часто встречаются незначительные различия. Из-за этих различий обработка CSV-файлов из разных источников может быть утомительной. Тем не менее, хотя разделители и символы кавычек различаются, общий формат достаточно схож, чтобы можно было написать один модуль, способный эффективно работать с такими данными, скрывая от программиста детали чтения и записи.1415Модуль [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) реализует классы для чтения и записи табличных данных в формате CSV. Он позволяет программистам сказать: «запиши эти данные в формате, предпочитаемом Excel» или «прочитай данные из этого файла, созданного Excel», не вдаваясь в точные детали формата CSV, используемого Excel. Программисты также могут описывать форматы CSV, используемые другими приложениями, или определять собственные специализированные форматы CSV.1617Объекты [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader) и [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) модуля [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) читают и записывают последовательности. Программисты также могут читать и записывать данные в словарной форме, используя классы [`DictReader`](https://python-all.ru/3.5/library/csv.html#csv.DictReader) и [`DictWriter`](https://python-all.ru/3.5/library/csv.html#csv.DictWriter).1819> **См. также**20>21> **[**PEP 305**](https://python-all.ru/3.5/library/csv.html) - API для CSV-файлов**22>23> Предложение по улучшению Python, в котором было предложено это дополнение.2425## 14.1.1. Содержание модуля2627Модуль [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) определяет следующие функции:2829#### `csv.reader(csvfile, dialect='excel', **fmtparams)`3031Возвращает объект reader, который перебирает строки в указанном *csvfile*. *csvfile* может быть любым объектом, поддерживающим протокол [итератора](https://python-all.ru/3.5/glossary.html#term-iterator) и возвращающим строку при каждом вызове метода `__next__()` – подходят как [файловые объекты](https://python-all.ru/3.5/glossary.html#term-file-object), так и списки. Если *csvfile* является файловым объектом, он должен быть открыт с `newline=''`. [\[1\]](https://python-all.ru/3.5/library/csv.html#id3) Можно указать необязательный параметр *dialect*, который задаёт набор параметров, специфичных для конкретного диалекта CSV. Он может быть экземпляром подкласса класса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect) или одной из строк, возвращаемых функцией [`list_dialects()`](https://python-all.ru/3.5/library/csv.html#csv.list_dialects). Остальные необязательные именованные аргументы *fmtparams* можно указать для переопределения отдельных параметров форматирования в текущем диалекте. Подробнее о диалекте и параметрах форматирования см. в разделе [Диалекты и параметры форматирования](https://python-all.ru/3.5/library/csv.html#csv-fmt-params).3233Каждая строка, прочитанная из CSV-файла, возвращается в виде списка строк. Автоматическое преобразование типов данных не выполняется, если не задан параметр формата `QUOTE_NONNUMERIC` (в этом случае незакавыченные поля преобразуются в числа с плавающей запятой).3435Краткий пример использования:3637```python38>>> import csv39>>> with open('eggs.csv', newline='') as csvfile:40...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')41...     for row in spamreader:42...         print(', '.join(row))43Spam, Spam, Spam, Spam, Spam, Baked Beans44Spam, Lovely Spam, Wonderful Spam45```4647#### `csv.writer(csvfile, dialect='excel', **fmtparams)`4849Возвращает объект writer, который преобразует данные пользователя в строки с разделителями и записывает их в переданный файлоподобный объект. *csvfile* может быть любым объектом, имеющим метод `write()`. Если *csvfile* – файловый объект, он должен быть открыт с `newline=''` [\[1\]](https://python-all.ru/3.5/library/csv.html#id3). Можно указать необязательный параметр *dialect*, который задаёт набор параметров для определённого диалекта CSV. Он может быть экземпляром подкласса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect) или одной из строк, возвращаемых функцией [`list_dialects()`](https://python-all.ru/3.5/library/csv.html#csv.list_dialects). Остальные необязательные именованные аргументы *fmtparams* можно задать, чтобы переопределить отдельные параметры форматирования в текущем диалекте. Подробнее о диалектах и параметрах форматирования см. раздел [Диалекты и параметры форматирования](https://python-all.ru/3.5/library/csv.html#csv-fmt-params). Чтобы упростить взаимодействие с модулями, реализующими DB API, значение [`None`](https://python-all.ru/3.5/library/constants.html#None) записывается как пустая строка. Хотя это преобразование не является обратимым, оно упрощает выгрузку значений SQL NULL в CSV-файлы без предварительной обработки данных, возвращаемых вызовом `cursor.fetch*`. Все остальные нестроковые данные преобразуются в строки с помощью [`str()`](https://python-all.ru/3.5/library/stdtypes.html#str) перед записью.5051Краткий пример использования:5253```python54import csv55with open('eggs.csv', 'w', newline='') as csvfile:56    spamwriter = csv.writer(csvfile, delimiter=' ',57                            quotechar='|', quoting=csv.QUOTE_MINIMAL)58    spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])59    spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])60```6162#### `csv.register_dialect(name[, dialect[, **fmtparams]])`6364Связывает *dialect* с *name*. *name* должен быть строкой. Диалект может быть задан передачей подкласса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect), или именованными аргументами *fmtparams*, или и тем и другим; именованные аргументы переопределяют параметры диалекта. Подробнее о диалектах и параметрах форматирования см. раздел [Диалекты и параметры форматирования](https://python-all.ru/3.5/library/csv.html#csv-fmt-params).6566#### `csv.unregister_dialect(name)`6768Удаляет диалект, связанный с *name*, из реестра диалектов. Возникает исключение [`Error`](https://python-all.ru/3.5/library/csv.html#csv.Error), если *name* не является зарегистрированным именем диалекта.6970#### `csv.get_dialect(name)`7172Возвращает диалект, связанный с *name*. Возникает исключение [`Error`](https://python-all.ru/3.5/library/csv.html#csv.Error), если *name* не является зарегистрированным именем диалекта. Эта функция возвращает неизменяемый [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect).7374#### `csv.list_dialects()`7576Возвращает имена всех зарегистрированных диалектов.7778#### `csv.field_size_limit([new_limit])`7980Возвращает текущий максимальный размер поля, разрешенный парсером. Если задан *new\_limit*, он становится новым лимитом.8182Модуль [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) определяет следующие классы:8384#### `class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)`8586Создаёт объект, который работает как обычный reader, но преобразует прочитанные данные в словарь, ключи которого задаются необязательным параметром *fieldnames*. Параметр *fieldnames* – это [`sequence`](https://python-all.ru/3.5/library/collections.abc.html#module-collections.abc), элементы которого связываются с полями входных данных по порядку. Эти элементы становятся ключами результирующего словаря. Если параметр *fieldnames* опущен, в качестве имён полей используются значения из первой строки *csvfile*. Если в прочитанной строке полей больше, чем в последовательности имён полей, оставшиеся данные добавляются в виде последовательности, ключом которой служит значение *restkey*. Если в прочитанной строке полей меньше, чем в последовательности имён полей, то оставшимся ключам присваивается значение необязательного параметра *restval*. Все остальные необязательные и ключевые аргументы передаются экземпляру [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader).8788Краткий пример использования:8990```python91>>> import csv92>>> with open('names.csv') as csvfile:93...     reader = csv.DictReader(csvfile)94...     for row in reader:95...         print(row['first_name'], row['last_name'])96...97Baked Beans98Lovely Spam99Wonderful Spam100```101102#### `class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)`103104Создаёт объект, который работает как обычный writer, но преобразует словари в выходные строки. Параметр *fieldnames* – это [`sequence`](https://python-all.ru/3.5/library/collections.abc.html#module-collections.abc) ключей, задающих порядок, в котором значения из словаря, переданного методу `writerow()`, записываются в *csvfile*. Необязательный параметр *restval* указывает значение, которое будет записано, если в словаре отсутствует ключ из *fieldnames*. Если словарь, переданный методу `writerow()`, содержит ключ, отсутствующий в *fieldnames*, необязательный параметр *extrasaction* определяет дальнейшие действия. Если он установлен в `'raise'`, возбуждается исключение [`ValueError`](https://python-all.ru/3.5/library/exceptions.html#ValueError). Если установлен в `'ignore'`, лишние значения в словаре игнорируются. Все остальные необязательные и ключевые аргументы передаются экземпляру [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer).105106Обратите внимание: в отличие от класса [`DictReader`](https://python-all.ru/3.5/library/csv.html#csv.DictReader), параметр *fieldnames* у [`DictWriter`](https://python-all.ru/3.5/library/csv.html#csv.DictWriter) не является необязательным. Поскольку объекты [`dict`](https://python-all.ru/3.5/library/stdtypes.html#dict) в Python не упорядочены, недостаточно информации для определения порядка, в котором строка должна быть записана в *csvfile*.107108Краткий пример использования:109110```python111import csv112113with open('names.csv', 'w') as csvfile:114    fieldnames = ['first_name', 'last_name']115    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)116117    writer.writeheader()118    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})119    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})120    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})121```122123#### `class csv.Dialect`124125Класс [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect) – это контейнерный класс, используемый в первую очередь для своих атрибутов, которые задают параметры для конкретного экземпляра [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader) или [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer).126127#### `class csv.excel`128129Класс [`excel`](https://python-all.ru/3.5/library/csv.html#csv.excel) определяет обычные свойства CSV-файла, созданного в Excel. Он зарегистрирован под именем диалекта `'excel'`.130131#### `class csv.excel_tab`132133Класс [`excel_tab`](https://python-all.ru/3.5/library/csv.html#csv.excel_tab) определяет обычные свойства файла с разделителями табуляции, созданного в Excel. Он зарегистрирован под именем диалекта `'excel-tab'`.134135#### `class csv.unix_dialect`136137Класс [`unix_dialect`](https://python-all.ru/3.5/library/csv.html#csv.unix_dialect) определяет обычные свойства CSV-файла, созданного в UNIX-системах, то есть использующего `'\n'` в качестве завершителя строк и заключающего все поля в кавычки. Он зарегистрирован под именем диалекта `'unix'`.138139Новое в версии 3.2.140141#### `class csv.Sniffer`142143Класс [`Sniffer`](https://python-all.ru/3.5/library/csv.html#csv.Sniffer) используется для определения формата CSV-файла.144145Класс [`Sniffer`](https://python-all.ru/3.5/library/csv.html#csv.Sniffer) предоставляет два метода:146147#### `sniff(sample, delimiters=None)`148149Анализирует переданный *sample* и возвращает подкласс [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect), отражающий найденные параметры. Если указан необязательный параметр *delimiters*, он интерпретируется как строка, содержащая возможные допустимые символы-разделители.150151#### `has_header(sample)`152153Анализирует образец текста (предположительно в формате CSV) и возвращает [`True`](https://python-all.ru/3.5/library/constants.html#True), если первая строка выглядит как набор заголовков столбцов.154155Пример использования [`Sniffer`](https://python-all.ru/3.5/library/csv.html#csv.Sniffer):156157```python158with open('example.csv') as csvfile:159    dialect = csv.Sniffer().sniff(csvfile.read(1024))160    csvfile.seek(0)161    reader = csv.reader(csvfile, dialect)162    # ... здесь обрабатывается содержимое CSV-файла ...163```164165Модуль [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) определяет следующие константы:166167#### `csv.QUOTE_ALL`168169Указывает объектам [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) заключать все поля в кавычки.170171#### `csv.QUOTE_MINIMAL`172173Указывает объектам [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) заключать в кавычки только те поля, которые содержат специальные символы, такие как *разделитель*, *символ кавычки* или любой из символов *терминатора строки*.174175#### `csv.QUOTE_NONNUMERIC`176177Указывает объектам [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) заключать все нечисловые поля в кавычки.178179Указывает объекту чтения преобразовывать все нецитируемые поля в тип *float*.180181#### `csv.QUOTE_NONE`182183Указывает объектам [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) никогда не заключать поля в кавычки. Если текущий *разделитель* встречается в выходных данных, перед ним ставится текущий символ *escapechar*. Если *escapechar* не задан, объект writer вызовет [`Error`](https://python-all.ru/3.5/library/csv.html#csv.Error), если встретятся символы, требующие экранирования.184185Указывает [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader) не выполнять специальной обработки символов кавычек.186187Модуль [`csv`](https://python-all.ru/3.5/library/csv.html#module-csv) определяет следующее исключение:188189#### `exception csv.Error`190191Возбуждается любой из функций при обнаружении ошибки.192193## 14.1.2. Диалекты и параметры форматирования194195Чтобы упростить задание формата входных и выходных записей, определённые параметры форматирования группируются в диалекты. Диалект – это подкласс класса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect), имеющий набор определённых методов и единственный метод `validate()`. При создании объектов [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader) или [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer) программист может указать в качестве параметра dialect строку или подкласс класса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect). В дополнение к параметру *dialect* или вместо него программист может также указать отдельные параметры форматирования, имена которых совпадают с атрибутами класса [`Dialect`](https://python-all.ru/3.5/library/csv.html#csv.Dialect), определёнными ниже.196197Диалекты поддерживают следующие атрибуты:198199#### `Dialect.delimiter`200201Односимвольная строка, используемая для разделения полей. По умолчанию равна `','`.202203#### `Dialect.doublequote`204205Управляет тем, как должны заключаться в кавычки экземпляры *quotechar*, встречающиеся внутри поля. Когда [`True`](https://python-all.ru/3.5/library/constants.html#True), символ удваивается. Когда [`False`](https://python-all.ru/3.5/library/constants.html#False), *escapechar* используется в качестве префикса для *quotechar*. По умолчанию [`True`](https://python-all.ru/3.5/library/constants.html#True).206207При выводе, если *doublequote* равно [`False`](https://python-all.ru/3.5/library/constants.html#False) и *escapechar* не задан, возбуждается [`Error`](https://python-all.ru/3.5/library/csv.html#csv.Error), если в поле обнаружен *quotechar*.208209#### `Dialect.escapechar`210211Односимвольная строка, используемая объектом writer для экранирования *разделителя*, если для *quoting* установлено значение [`QUOTE_NONE`](https://python-all.ru/3.5/library/csv.html#csv.QUOTE_NONE), и *quotechar*, если *doublequote* равно [`False`](https://python-all.ru/3.5/library/constants.html#False). При чтении *escapechar* снимает особое значение со следующего символа. По умолчанию [`None`](https://python-all.ru/3.5/library/constants.html#None), что отключает экранирование.212213#### `Dialect.lineterminator`214215Строка, используемая для завершения строк, создаваемых [`writer`](https://python-all.ru/3.5/library/csv.html#csv.writer). По умолчанию равна `'\r\n'`.216217> **Примечание**218>219> Модуль [`reader`](https://python-all.ru/3.5/library/csv.html#csv.reader) жёстко запрограммирован распознавать `'\r'` или `'\n'` как конец строки и игнорировать *lineterminator*. В будущем это поведение может измениться.220221#### `Dialect.quotechar`222223Односимвольная строка, используемая для заключения в кавычки полей, содержащих специальные символы, такие как *разделитель* или *quotechar*, или содержащих символы новой строки. По умолчанию `'"'`.224225#### `Dialect.quoting`226227Управляет тем, когда кавычки должны генерироваться писателем (writer) и распознаваться читателем (reader). Может принимать любое из значений констант `QUOTE_*` (см. раздел [Содержание модуля](https://python-all.ru/3.5/library/csv.html#csv-contents)); по умолчанию [`QUOTE_MINIMAL`](https://python-all.ru/3.5/library/csv.html#csv.QUOTE_MINIMAL).228229#### `Dialect.skipinitialspace`230231Когда [`True`](https://python-all.ru/3.5/library/constants.html#True), пробелы сразу после *разделителя* игнорируются. По умолчанию [`False`](https://python-all.ru/3.5/library/constants.html#False).232233#### `Dialect.strict`234235Если `True`, при некорректном CSV-вводе вызывается исключение [`Error`](https://python-all.ru/3.5/library/csv.html#csv.Error). По умолчанию `False`.236237## 14.1.3. Объекты Reader238239Объекты reader (экземпляры [`DictReader`](https://python-all.ru/3.5/library/csv.html#csv.DictReader) и объекты, возвращаемые функцией [`reader()`](https://python-all.ru/3.5/library/csv.html#csv.reader)) имеют следующие открытые методы:240241#### `csvreader.__next__()`242243Возвращает следующую строку итерируемого объекта reader в виде списка (если объект был возвращён из [`reader()`](https://python-all.ru/3.5/library/csv.html#csv.reader)) или словаря (если это экземпляр [`DictReader`](https://python-all.ru/3.5/library/csv.html#csv.DictReader)), разобранную в соответствии с текущим диалектом. Обычно это следует вызывать как `next(reader)`.244245Объекты reader имеют следующие открытые атрибуты:246247#### `csvreader.dialect`248249Доступное только для чтения описание диалекта, используемого синтаксическим анализатором.250251#### `csvreader.line_num`252253Количество строк, прочитанных из итератора-источника. Это число не совпадает с количеством возвращённых записей, так как записи могут занимать несколько строк.254255Объекты DictReader имеют следующий открытый атрибут:256257#### `csvreader.fieldnames`258259Если этот атрибут не был передан в качестве параметра при создании объекта, он инициализируется при первом обращении или при чтении первой записи из файла.260261## 14.1.4. Объекты Writer262263Объекты `Writer` (экземпляры [`DictWriter`](https://python-all.ru/3.5/library/csv.html#csv.DictWriter) и объекты, возвращаемые функцией [`writer()`](https://python-all.ru/3.5/library/csv.html#csv.writer)) имеют следующие открытые методы. Параметр *row* должен быть итерацией строк или чисел для объектов `Writer` и словарём, сопоставляющим имена полей со строками или числами (предварительно пропустив их через [`str()`](https://python-all.ru/3.5/library/stdtypes.html#str)) для объектов [`DictWriter`](https://python-all.ru/3.5/library/csv.html#csv.DictWriter). Обратите внимание, что комплексные числа записываются в круглых скобках. Это может вызвать некоторые проблемы для других программ, читающих CSV-файлы (если они вообще поддерживают комплексные числа).264265#### `csvwriter.writerow(row)`266267Записывает параметр *row* в файловый объект writer, отформатировав в соответствии с текущим диалектом.268269Изменено в версии 3.5: Добавлена поддержка произвольных итераций.270271#### `csvwriter.writerows(rows)`272273Записывает все параметры *rows* (список объектов *row*, как описано выше) в файловый объект writer, форматируя в соответствии с текущим диалектом.274275Объекты Writer имеют следующий открытый атрибут:276277#### `csvwriter.dialect`278279Описание диалекта, используемого средством записи, доступное только для чтения.280281Объекты DictWriter имеют следующий открытый метод:282283#### `DictWriter.writeheader()`284285Записывает строку с названиями полей (как указано в конструкторе).286287Новое в версии 3.2.288289## 14.1.5. Примеры290291Простейший пример чтения CSV-файла:292293```python294import csv295with open('some.csv', newline='') as f:296    reader = csv.reader(f)297    for row in reader:298        print(row)299```300301Чтение файла в альтернативном формате:302303```python304import csv305with open('passwd', newline='') as f:306    reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)307    for row in reader:308        print(row)309```310311Соответствующий простейший пример записи:312313```python314import csv315with open('some.csv', 'w', newline='') as f:316    writer = csv.writer(f)317    writer.writerows(someiterable)318```319320Поскольку [`open()`](https://python-all.ru/3.5/library/functions.html#open) используется для открытия CSV-файла для чтения, файл по умолчанию будет декодирован в Unicode с использованием системной кодировки по умолчанию (см. [`locale.getpreferredencoding()`](https://python-all.ru/3.5/library/locale.html#locale.getpreferredencoding)). Чтобы декодировать файл с другой кодировкой, используйте аргумент `encoding` функции open:321322```python323import csv324with open('some.csv', newline='', encoding='utf-8') as f:325    reader = csv.reader(f)326    for row in reader:327        print(row)328```329330То же самое относится к записи в кодировке, отличной от системной: укажите аргумент encoding при открытии выходного файла.331332Регистрация нового диалекта:333334```python335import csv336csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)337with open('passwd', newline='') as f:338    reader = csv.reader(f, 'unixpwd')339```340341Чуть более продвинутое использование reader – перехват и сообщение об ошибках:342343```python344import csv, sys345filename = 'some.csv'346with open(filename, newline='') as f:347    reader = csv.reader(f)348    try:349        for row in reader:350            print(row)351    except csv.Error as e:352        sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))353```354355И хотя модуль напрямую не поддерживает разбор строк, это можно легко сделать:356357```python358import csv359for row in csv.reader(['one,two,three']):360    print(row)361```362363Сноски364365| \[1\] | *([1](https://python-all.ru/3.5/library/csv.html#id1), [2](https://python-all.ru/3.5/library/csv.html#id2))* Если `newline=''` не указан, символы новой строки внутри заключённых в кавычки полей будут интерпретироваться неверно, а на платформах, использующих `\r\n` окончания строк, при записи будет добавлен лишний `\r`. Всегда безопасно указывать `newline=''`, поскольку модуль csv выполняет собственную обработку новых строк ([универсальную](https://python-all.ru/3.5/glossary.html#term-universal-newlines)). |366| --- | --- |367