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

csv.md

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

1> **Источник:** https://python-all.ru/3.6/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.6/library/csv.html#module-csv)– чтение и запись CSV-файлов89**Исходный код:** [Lib/csv.py](https://python-all.ru/src/3.6/Lib/csv.py)1011---1213Так называемый формат CSV (Comma Separated Values) – самый распространенный формат импорта и экспорта для электронных таблиц и баз данных. Формат CSV использовался много лет до попыток дать ему стандартизированное описание в [**RFC 4180**](https://python-all.ru/3.6/library/csv.html). Отсутствие четкого стандарта приводит к тому, что в данных, создаваемых и используемых разными приложениями, часто встречаются незначительные различия. Из-за этих различий обработка CSV-файлов из разных источников может быть утомительной. Тем не менее, хотя разделители и символы кавычек различаются, общий формат достаточно схож, чтобы можно было написать один модуль, способный эффективно работать с такими данными, скрывая от программиста детали чтения и записи.1415Модуль [`csv`](https://python-all.ru/3.6/library/csv.html#module-csv) реализует классы для чтения и записи табличных данных в формате CSV. Он позволяет программистам сказать: «запиши эти данные в формате, предпочитаемом Excel» или «прочитай данные из этого файла, созданного Excel», не вдаваясь в точные детали формата CSV, используемого Excel. Программисты также могут описывать форматы CSV, используемые другими приложениями, или определять собственные специализированные форматы CSV.1617Объекты [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader) и [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) модуля [`csv`](https://python-all.ru/3.6/library/csv.html#module-csv) читают и записывают последовательности. Программисты также могут читать и записывать данные в словарной форме, используя классы [`DictReader`](https://python-all.ru/3.6/library/csv.html#csv.DictReader) и [`DictWriter`](https://python-all.ru/3.6/library/csv.html#csv.DictWriter).1819> **См. также**20>21> **[**PEP 305**](https://python-all.ru/3.6/library/csv.html) - API для CSV-файлов**22>23> Предложение по улучшению Python, в котором было предложено это дополнение.2425## 14.1.1. Содержание модуля2627Модуль [`csv`](https://python-all.ru/3.6/library/csv.html#module-csv) определяет следующие функции:2829#### `csv.reader(csvfile, dialect='excel', **fmtparams)`3031Возвращает объект reader, который перебирает строки в указанном *csvfile*. *csvfile* может быть любым объектом, поддерживающим протокол [итератора](https://python-all.ru/3.6/glossary.html#term-iterator) и возвращающим строку при каждом вызове метода `__next__()` – подходят как [файловые объекты](https://python-all.ru/3.6/glossary.html#term-file-object), так и списки. Если *csvfile* является файловым объектом, он должен быть открыт с `newline=''`. [1](https://python-all.ru/3.6/library/csv.html#id3) Можно указать необязательный параметр *dialect*, который задаёт набор параметров, специфичных для конкретного диалекта CSV. Он может быть экземпляром подкласса класса [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect) или одной из строк, возвращаемых функцией [`list_dialects()`](https://python-all.ru/3.6/library/csv.html#csv.list_dialects). Остальные необязательные именованные аргументы *fmtparams* можно указать для переопределения отдельных параметров форматирования в текущем диалекте. Подробнее о диалекте и параметрах форматирования см. в разделе [Диалекты и параметры форматирования](https://python-all.ru/3.6/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.6/library/csv.html#id3). Можно указать необязательный параметр *dialect*, который задаёт набор параметров для определённого диалекта CSV. Он может быть экземпляром подкласса [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect) или одной из строк, возвращаемых функцией [`list_dialects()`](https://python-all.ru/3.6/library/csv.html#csv.list_dialects). Остальные необязательные именованные аргументы *fmtparams* можно задать, чтобы переопределить отдельные параметры форматирования в текущем диалекте. Подробнее о диалектах и параметрах форматирования см. раздел [Диалекты и параметры форматирования](https://python-all.ru/3.6/library/csv.html#csv-fmt-params). Чтобы упростить взаимодействие с модулями, реализующими DB API, значение [`None`](https://python-all.ru/3.6/library/constants.html#None) записывается как пустая строка. Хотя это преобразование не является обратимым, оно упрощает выгрузку значений SQL NULL в CSV-файлы без предварительной обработки данных, возвращаемых вызовом `cursor.fetch*`. Все остальные нестроковые данные преобразуются в строки с помощью [`str()`](https://python-all.ru/3.6/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.6/library/csv.html#csv.Dialect), или именованными аргументами *fmtparams*, или и тем и другим; именованные аргументы переопределяют параметры диалекта. Подробнее о диалектах и параметрах форматирования см. раздел [Диалекты и параметры форматирования](https://python-all.ru/3.6/library/csv.html#csv-fmt-params).6566#### `csv.unregister_dialect(name)`6768Удаляет диалект, связанный с *name*, из реестра диалектов. Возникает исключение [`Error`](https://python-all.ru/3.6/library/csv.html#csv.Error), если *name* не является зарегистрированным именем диалекта.6970#### `csv.get_dialect(name)`7172Возвращает диалект, связанный с *name*. Возникает исключение [`Error`](https://python-all.ru/3.6/library/csv.html#csv.Error), если *name* не является зарегистрированным именем диалекта. Эта функция возвращает неизменяемый [`Dialect`](https://python-all.ru/3.6/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.6/library/csv.html#module-csv) определяет следующие классы:8384#### `class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)`8586Создаёт объект, который работает как обычный reader, но сопоставляет информацию из каждой строки с [`OrderedDict`](https://python-all.ru/3.6/library/collections.html#collections.OrderedDict), ключи которого задаются необязательным параметром *fieldnames*.8788Параметр *fieldnames* – это [последовательность](https://python-all.ru/3.6/glossary.html#term-sequence). Если *fieldnames* опущен, в качестве названий полей используются значения первой строки файла *f*. Независимо от того, как определяются названия полей, упорядоченный словарь сохраняет их исходный порядок.8990Если строка содержит больше полей, чем fieldnames, оставшиеся данные помещаются в список и сохраняются с именем поля, указанным в *restkey* (по умолчанию `None`). Если непустая строка содержит меньше полей, чем fieldnames, недостающие значения заполняются `None`.9192Все остальные необязательные и именованные аргументы передаются базовому экземпляру [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader).9394Изменено в версии 3.6: Возвращаемые строки теперь имеют тип `OrderedDict`.9596Краткий пример использования:9798```python99>>> import csv100>>> with open('names.csv', newline='') as csvfile:101...     reader = csv.DictReader(csvfile)102...     for row in reader:103...         print(row['first_name'], row['last_name'])104...105Eric Idle106John Cleese107108>>> print(row)109OrderedDict([('first_name', 'John'), ('last_name', 'Cleese')])110```111112#### `class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)`113114Создаёт объект, который работает как обычный writer, но отображает словари на выходные строки. Параметр *fieldnames* – это [`sequence`](https://python-all.ru/3.6/library/collections.abc.html#module-collections.abc) ключей, определяющих порядок, в котором значения из словаря, переданного методу `writerow()`, записываются в файл *f*. Необязательный параметр *restval* задаёт значение, которое будет записано, если в словаре отсутствует ключ из *fieldnames*. Если словарь, переданный методу `writerow()`, содержит ключ, отсутствующий в *fieldnames*, необязательный параметр *extrasaction* указывает, какие действия предпринять. Если он установлен в `'raise'` (значение по умолчанию), возбуждается [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError). Если он установлен в `'ignore'`, дополнительные значения в словаре игнорируются. Все остальные необязательные и именованные аргументы передаются базовому экземпляру [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer).115116Обратите внимание, что в отличие от класса [`DictReader`](https://python-all.ru/3.6/library/csv.html#csv.DictReader), параметр *fieldnames* в [`DictWriter`](https://python-all.ru/3.6/library/csv.html#csv.DictWriter) не является необязательным. Поскольку объекты [`dict`](https://python-all.ru/3.6/library/stdtypes.html#dict) в Python не упорядочены, недостаточно информации, чтобы определить порядок, в котором строка должна быть записана в файл *f*.117118Краткий пример использования:119120```python121import csv122123with open('names.csv', 'w', newline='') as csvfile:124    fieldnames = ['first_name', 'last_name']125    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)126127    writer.writeheader()128    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})129    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})130    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})131```132133#### `class csv.Dialect`134135Класс [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect) – это контейнерный класс, используемый в первую очередь для своих атрибутов, которые задают параметры для конкретного экземпляра [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader) или [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer).136137#### `class csv.excel`138139Класс [`excel`](https://python-all.ru/3.6/library/csv.html#csv.excel) определяет обычные свойства CSV-файла, созданного в Excel. Он зарегистрирован под именем диалекта `'excel'`.140141#### `class csv.excel_tab`142143Класс [`excel_tab`](https://python-all.ru/3.6/library/csv.html#csv.excel_tab) определяет обычные свойства файла с разделителями табуляции, созданного в Excel. Он зарегистрирован под именем диалекта `'excel-tab'`.144145#### `class csv.unix_dialect`146147Класс [`unix_dialect`](https://python-all.ru/3.6/library/csv.html#csv.unix_dialect) определяет обычные свойства CSV-файла, созданного в UNIX-системах, то есть использующего `'\n'` в качестве завершителя строк и заключающего все поля в кавычки. Он зарегистрирован под именем диалекта `'unix'`.148149Новое в версии 3.2.150151#### `class csv.Sniffer`152153Класс [`Sniffer`](https://python-all.ru/3.6/library/csv.html#csv.Sniffer) используется для определения формата CSV-файла.154155Класс [`Sniffer`](https://python-all.ru/3.6/library/csv.html#csv.Sniffer) предоставляет два метода:156157#### `sniff(sample, delimiters=None)`158159Анализирует переданный *sample* и возвращает подкласс [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect), отражающий найденные параметры. Если указан необязательный параметр *delimiters*, он интерпретируется как строка, содержащая возможные допустимые символы-разделители.160161#### `has_header(sample)`162163Анализирует образец текста (предположительно в формате CSV) и возвращает [`True`](https://python-all.ru/3.6/library/constants.html#True), если первая строка выглядит как набор заголовков столбцов.164165Пример использования [`Sniffer`](https://python-all.ru/3.6/library/csv.html#csv.Sniffer):166167```python168with open('example.csv', newline='') as csvfile:169    dialect = csv.Sniffer().sniff(csvfile.read(1024))170    csvfile.seek(0)171    reader = csv.reader(csvfile, dialect)172    # ... здесь обрабатывается содержимое CSV-файла ...173```174175Модуль [`csv`](https://python-all.ru/3.6/library/csv.html#module-csv) определяет следующие константы:176177#### `csv.QUOTE_ALL`178179Указывает объектам [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) заключать все поля в кавычки.180181#### `csv.QUOTE_MINIMAL`182183Указывает объектам [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) заключать в кавычки только те поля, которые содержат специальные символы, такие как *разделитель*, *символ кавычки* или любой из символов *терминатора строки*.184185#### `csv.QUOTE_NONNUMERIC`186187Указывает объектам [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) заключать все нечисловые поля в кавычки.188189Указывает объекту чтения преобразовывать все нецитируемые поля в тип *float*.190191#### `csv.QUOTE_NONE`192193Указывает объектам [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) никогда не заключать поля в кавычки. Если текущий *разделитель* встречается в выходных данных, перед ним ставится текущий символ *escapechar*. Если *escapechar* не задан, объект writer вызовет [`Error`](https://python-all.ru/3.6/library/csv.html#csv.Error), если встретятся символы, требующие экранирования.194195Указывает [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader) не выполнять специальной обработки символов кавычек.196197Модуль [`csv`](https://python-all.ru/3.6/library/csv.html#module-csv) определяет следующее исключение:198199#### `exception csv.Error`200201Возбуждается любой из функций при обнаружении ошибки.202203## 14.1.2. Диалекты и параметры форматирования204205Чтобы упростить задание формата входных и выходных записей, определённые параметры форматирования группируются в диалекты. Диалект – это подкласс класса [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect), имеющий набор определённых методов и единственный метод `validate()`. При создании объектов [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader) или [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer) программист может указать в качестве параметра dialect строку или подкласс класса [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect). В дополнение к параметру *dialect* или вместо него программист может также указать отдельные параметры форматирования, имена которых совпадают с атрибутами класса [`Dialect`](https://python-all.ru/3.6/library/csv.html#csv.Dialect), определёнными ниже.206207Диалекты поддерживают следующие атрибуты:208209#### `Dialect.delimiter`210211Односимвольная строка, используемая для разделения полей. По умолчанию равна `','`.212213#### `Dialect.doublequote`214215Управляет тем, как должны заключаться в кавычки экземпляры *quotechar*, встречающиеся внутри поля. Когда [`True`](https://python-all.ru/3.6/library/constants.html#True), символ удваивается. Когда [`False`](https://python-all.ru/3.6/library/constants.html#False), *escapechar* используется в качестве префикса для *quotechar*. По умолчанию [`True`](https://python-all.ru/3.6/library/constants.html#True).216217При выводе, если *doublequote* равно [`False`](https://python-all.ru/3.6/library/constants.html#False) и *escapechar* не задан, возбуждается [`Error`](https://python-all.ru/3.6/library/csv.html#csv.Error), если в поле обнаружен *quotechar*.218219#### `Dialect.escapechar`220221Односимвольная строка, используемая объектом writer для экранирования *разделителя*, если для *quoting* установлено значение [`QUOTE_NONE`](https://python-all.ru/3.6/library/csv.html#csv.QUOTE_NONE), и *quotechar*, если *doublequote* равно [`False`](https://python-all.ru/3.6/library/constants.html#False). При чтении *escapechar* снимает особое значение со следующего символа. По умолчанию [`None`](https://python-all.ru/3.6/library/constants.html#None), что отключает экранирование.222223#### `Dialect.lineterminator`224225Строка, используемая для завершения строк, создаваемых [`writer`](https://python-all.ru/3.6/library/csv.html#csv.writer). По умолчанию равна `'\r\n'`.226227> **Примечание**228>229> Модуль [`reader`](https://python-all.ru/3.6/library/csv.html#csv.reader) жёстко запрограммирован распознавать `'\r'` или `'\n'` как конец строки и игнорировать *lineterminator*. В будущем это поведение может измениться.230231#### `Dialect.quotechar`232233Односимвольная строка, используемая для заключения в кавычки полей, содержащих специальные символы, такие как *разделитель* или *quotechar*, или содержащих символы новой строки. По умолчанию `'"'`.234235#### `Dialect.quoting`236237Управляет тем, когда кавычки должны генерироваться писателем (writer) и распознаваться читателем (reader). Может принимать любое из значений констант `QUOTE_*` (см. раздел [Содержание модуля](https://python-all.ru/3.6/library/csv.html#csv-contents)); по умолчанию [`QUOTE_MINIMAL`](https://python-all.ru/3.6/library/csv.html#csv.QUOTE_MINIMAL).238239#### `Dialect.skipinitialspace`240241Когда [`True`](https://python-all.ru/3.6/library/constants.html#True), пробелы сразу после *разделителя* игнорируются. По умолчанию [`False`](https://python-all.ru/3.6/library/constants.html#False).242243#### `Dialect.strict`244245Если `True`, при некорректном CSV-вводе вызывается исключение [`Error`](https://python-all.ru/3.6/library/csv.html#csv.Error). По умолчанию `False`.246247## 14.1.3. Объекты Reader248249Объекты reader (экземпляры [`DictReader`](https://python-all.ru/3.6/library/csv.html#csv.DictReader) и объекты, возвращаемые функцией [`reader()`](https://python-all.ru/3.6/library/csv.html#csv.reader)) имеют следующие открытые методы:250251#### `csvreader.__next__()`252253Возвращает следующую строку итерируемого объекта reader в виде списка (если объект был возвращён из [`reader()`](https://python-all.ru/3.6/library/csv.html#csv.reader)) или словаря (если это экземпляр [`DictReader`](https://python-all.ru/3.6/library/csv.html#csv.DictReader)), разобранную в соответствии с текущим диалектом. Обычно это следует вызывать как `next(reader)`.254255Объекты reader имеют следующие открытые атрибуты:256257#### `csvreader.dialect`258259Доступное только для чтения описание диалекта, используемого синтаксическим анализатором.260261#### `csvreader.line_num`262263Количество строк, прочитанных из итератора-источника. Это число не совпадает с количеством возвращённых записей, так как записи могут занимать несколько строк.264265Объекты DictReader имеют следующий открытый атрибут:266267#### `csvreader.fieldnames`268269Если этот атрибут не был передан в качестве параметра при создании объекта, он инициализируется при первом обращении или при чтении первой записи из файла.270271## 14.1.4. Объекты Writer272273Объекты `Writer` (экземпляры [`DictWriter`](https://python-all.ru/3.6/library/csv.html#csv.DictWriter) и объекты, возвращаемые функцией [`writer()`](https://python-all.ru/3.6/library/csv.html#csv.writer)) имеют следующие открытые методы. Параметр *row* должен быть итерацией строк или чисел для объектов `Writer` и словарём, сопоставляющим имена полей со строками или числами (предварительно пропустив их через [`str()`](https://python-all.ru/3.6/library/stdtypes.html#str)) для объектов [`DictWriter`](https://python-all.ru/3.6/library/csv.html#csv.DictWriter). Обратите внимание, что комплексные числа записываются в круглых скобках. Это может вызвать некоторые проблемы для других программ, читающих CSV-файлы (если они вообще поддерживают комплексные числа).274275#### `csvwriter.writerow(row)`276277Записывает параметр *row* в файловый объект writer, отформатировав в соответствии с текущим диалектом.278279Изменено в версии 3.5: Добавлена поддержка произвольных итераций.280281#### `csvwriter.writerows(rows)`282283Записывает все элементы из *rows* (итерацию объектов *row*, как описано выше) в файловый объекта средства записи, форматируя в соответствии с текущим диалектом.284285Объекты Writer имеют следующий открытый атрибут:286287#### `csvwriter.dialect`288289Описание диалекта, используемого средством записи, доступное только для чтения.290291Объекты DictWriter имеют следующий открытый метод:292293#### `DictWriter.writeheader()`294295Записывает строку с названиями полей (как указано в конструкторе).296297Новое в версии 3.2.298299## 14.1.5. Примеры300301Простейший пример чтения CSV-файла:302303```python304import csv305with open('some.csv', newline='') as f:306    reader = csv.reader(f)307    for row in reader:308        print(row)309```310311Чтение файла в альтернативном формате:312313```python314import csv315with open('passwd', newline='') as f:316    reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)317    for row in reader:318        print(row)319```320321Соответствующий простейший пример записи:322323```python324import csv325with open('some.csv', 'w', newline='') as f:326    writer = csv.writer(f)327    writer.writerows(someiterable)328```329330Поскольку [`open()`](https://python-all.ru/3.6/library/functions.html#open) используется для открытия CSV-файла для чтения, файл по умолчанию будет декодирован в Unicode с использованием системной кодировки по умолчанию (см. [`locale.getpreferredencoding()`](https://python-all.ru/3.6/library/locale.html#locale.getpreferredencoding)). Чтобы декодировать файл с другой кодировкой, используйте аргумент `encoding` функции open:331332```python333import csv334with open('some.csv', newline='', encoding='utf-8') as f:335    reader = csv.reader(f)336    for row in reader:337        print(row)338```339340То же самое относится к записи в кодировке, отличной от системной: укажите аргумент encoding при открытии выходного файла.341342Регистрация нового диалекта:343344```python345import csv346csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)347with open('passwd', newline='') as f:348    reader = csv.reader(f, 'unixpwd')349```350351Чуть более продвинутое использование reader – перехват и сообщение об ошибках:352353```python354import csv, sys355filename = 'some.csv'356with open(filename, newline='') as f:357    reader = csv.reader(f)358    try:359        for row in reader:360            print(row)361    except csv.Error as e:362        sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))363```364365И хотя модуль напрямую не поддерживает разбор строк, это можно легко сделать:366367```python368import csv369for row in csv.reader(['one,two,three']):370    print(row)371```372373Сноски374375**1([1](https://python-all.ru/3.6/library/csv.html#id1),[2](https://python-all.ru/3.6/library/csv.html#id2))**376377Если `newline=''` не указан, символы новой строки внутри полей в кавычках не будут интерпретироваться правильно, и на платформах, использующих `\r\n` окончания строк, при записи будет добавлен лишний `\r`. Всегда безопасно указывать `newline=''`, поскольку модуль csv выполняет свою собственную ([универсальную](https://python-all.ru/3.6/glossary.html#term-universal-newlines)) обработку символов новой строки.378