CSV-файл, написанный на Python, содержит пустые строки между каждой строкой

446
import csv

with open('thefile.csv', 'rb') as f:
  data = list(csv.reader(f))
  import collections
  counter = collections.defaultdict(int)

  for row in data:
        counter[row[10]] += 1


with open('/pythonwork/thefile_subset11.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in data:
        if counter[row[10]] >= 504:
           writer.writerow(row)

Этот код читает thefile.csv, вносит изменения и записывает результаты thefile_subset1.

Однако, когда я открываю полученный CSV-файл в Microsoft Excel, после каждой записи появляется дополнительная пустая строка!

Есть ли способ заставить его не ставить лишнюю пустую строку?

л --''''''--------- «» «» «» «» «» «»
источник
4
Пожалуйста, подтвердите, что это происходит, когда вы запускаете этот код в Windows
Джон Мачин
Возможный дубликат Python 2 CSV
John Y
Смотрите ответ в этой теме: stackoverflow.com/questions/3348460/…
Февин Мэтью

Ответы:

889

В Python 2 откройте outfileрежим 'wb'вместо 'w'. csv.writerПишет \r\nв файл напрямую. Если вы не откроете файл в двоичном режиме, он напишет, \r\r\nпотому что в Windows текстовый режим переведет каждый \nв \r\n.

В Python 3 изменился необходимый синтаксис (см. Ссылки на документацию ниже), поэтому откройте его outfileс помощью дополнительного параметра newline=''(пустая строка).

Примеры:

# Python 2
with open('/pythonwork/thefile_subset11.csv', 'wb') as outfile:
    writer = csv.writer(outfile)

# Python 3
with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
    writer = csv.writer(outfile)

Документация Ссылки

Марк Толонен
источник
1
В любом случае, ответ @Mark Tolonen решил многие вопросы, связанные с дополнительными строками, добавленными при сохранении стандартного (без использования csv) текстового файла.
dlewin
1
Для совместимости между 2.6 / 2.7 и 3 вы можете использовать io.openс newlinesаргументом. Если вы все еще пишете в 2.x, это все равно кажется лучшим выбором, так как он совместим с форвардом.
jpmc26
@ jpmc26 Обычно это хороший совет, но модуль csv не работает должным образом io.open. Существует unicodecsvсторонний модуль для Python 2.7, который работает лучше.
Марк Толонен
Есть идеи, почему newline=''трюк не работает в python3 со StringIO или TemporaryFile?
fmoo
@fmoo определяет "не работает". Они оба работают так, как я ожидаю. StringIOбуферизует те же самые кодовые точки, которые будут закодированы в файл, и TemporaryFileподдерживает newlineпараметр, поэтому его можно открыть как с open. Задайте вопрос с примером программы, которая не работает.
Марк Толонен
65

Открытие файла в двоичном режиме «wb» не будет работать в Python 3+. Или, скорее, вам придется преобразовать ваши данные в двоичный файл перед записью. Это просто хлопот.

Вместо этого вы должны оставить его в текстовом режиме, но переопределить новую строку как пустую. Вот так:

with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
Дэвид Мэддокс
источник
13

Простой ответ заключается в том, что CSV-файлы всегда следует открывать в двоичном режиме для ввода или вывода, так как в противном случае в Windows возникают проблемы с окончанием строки. Конкретно на выходе модуль CSV будет написать \r\n(стандартный CSV строки терминатор) , а затем (в текстовом режиме) среда выполнения придет на смену \nпутем \r\n(стандартной линии терминатора Windows) дает результат \r\r\n.

Возиться с lineterminatorне является решением.

Джон Мачин
источник
Что это за «стандарт» CSV, о котором вы говорите?
Дэн Бреслау
3
@Dan: я использовал «стандарт» как прилагательное, а не существительное, что означает «обычный» или «обычное». Если вы хотите приблизиться к (существительному) стандарту, прочитайте tools.ietf.org/html/rfc4180
Джон Мачин
1
Дело в том (как вы подразумеваете), что не существует стандарта. Это РСЕ информационное. Хотя \ r \ n может быть "стандартным" в Windows, я уверен, что приложения Unix обычно не видят этого.
Дэн Бреслау
2
@ Дан: Это правильно - нет стандарта. В сценариях должен быть указан определитель строки [должен был называться ROWterminator], который они хотят (если не по умолчанию), и по-прежнему использовать двоичный режим в случае, если сценарий запускается в Windows, в противном случае «ограничитель строки» может быть заполнен.
Джон Мачин
8

Примечание: кажется, что это не предпочтительное решение из-за того, как дополнительная система была добавлена ​​в системе Windows. Как указано в документе Python :

Если csvfile является файловым объектом, он должен быть открыт с флагом 'b' на платформах, где это имеет значение.

Windows - одна из таких платформ, где это имеет значение. Хотя изменение разделителя строки, как я описал ниже, возможно, решило проблему, проблему можно полностью избежать, открыв файл в двоичном режиме. Можно сказать, что это решение более «элегантно». В этом случае «путаница» с ограничителем строки, вероятно, привела бы к непереносимости кода между системами, когда открытие файла в двоичном режиме в системе Unix не дает никакого эффекта. то есть. это приводит к кросс-совместимому коду.

Из документов Python :

В Windows добавленный к режиму «b» открывает файл в двоичном режиме, поэтому существуют также режимы, такие как «rb», «wb» и «r + b». Python в Windows делает различие между текстовыми и двоичными файлами; символы конца строки в текстовых файлах автоматически слегка изменяются при чтении или записи данных. Это закулисное изменение данных файла подходит для текстовых файлов ASCII, но оно повредит двоичные данные, подобные этим в файлах JPEG или EXE. Будьте очень осторожны, используя двоичный режим при чтении и записи таких файлов. В Unix не помешает добавить 'b' в режим, так что вы можете использовать его независимо от платформы для всех двоичных файлов.

Оригинал :

Как часть необязательных параметров для csv.writer, если вы получаете дополнительные пустые строки, вам, возможно, придется изменить определитель строки (информация здесь ). Пример ниже адаптирован со страницы Python CSV DOCS. Измените его с '\ n' на тот, который должен быть. Поскольку это всего лишь попытка решить проблему, это может или не может сработать, но это мое лучшее предположение.

>>> import csv
>>> spamWriter = csv.writer(open('eggs.csv', 'w'), lineterminator='\n')
>>> spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
>>> spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
Дерек Лиц
источник
Я собирался написать об этом - lineterminator = '\ n' работал для меня в простом тесте.
Дэн Бреслау
могу ли я сделать это> ?? с открытым ('/ pythonwork / thefile_subset11.csv', 'w'), lineterminator = '\ n' в качестве
выходного файла
1
@I__: Вы действительно должны начать просматривать документы Python. Дерек дал вам ссылку: docs.python.org/library/csv.html
Дэн Бреслау
5

Я пишу этот ответ по отношению к Python 3, так как у меня изначально возникла та же проблема.

Я должен был получить данные из Arduino, используя PySerial, и записать их в файл .csv. Каждое чтение в моем случае заканчивалось '\r\n', поэтому новая строка всегда разделяла каждую строку.

В моем случае newline=''опция не сработала. Потому что это показало какую-то ошибку вроде:

with open('op.csv', 'a',newline=' ') as csv_file:

ValueError: illegal newline value: ''

Таким образом, казалось, что они не принимают пропуска новой строки здесь.

Видя только один из ответов здесь, я упомянул терминатор строки в объекте записи, например,

writer = csv.writer(csv_file, delimiter=' ',lineterminator='\r')

и это помогло мне пропустить лишние переводы строк.

Дебанжан Дей
источник
2
Это неверно with open('my_file.csv', 'a',newline='') as csvfile: работает абсолютно нормально. Проблема с вашим ответом состоит в том, что здесь вы пишете ' 'вместо''
Nasrin
2
with open(destPath+'\\'+csvXML, 'a+') as csvFile:
    writer = csv.writer(csvFile, delimiter=';', lineterminator='\r')
    writer.writerows(xmlList)

"Lineterminator = '\ r'" позволяет перейти к следующей строке, без пустой строки между двумя.

Шера
источник
1

Исходя из этого ответа , кажется, что самое чистое решение - это использовать io.TextIOWrapper. Мне удалось решить эту проблему для себя следующим образом:

from io import TextIOWrapper

...

with open(filename, 'wb') as csvfile, TextIOWrapper(csvfile, encoding='utf-8', newline='') as wrapper:
    csvwriter = csv.writer(wrapper)
    for data_row in data:
        csvwriter.writerow(data_row)

Ответ выше не совместим с Python 2. Для обеспечения совместимости, я полагаю, нужно просто обернуть всю логику записи в ifблок:

if sys.version_info < (3,):
    # Python 2 way of handling CSVs
else:
    # The above logic
фантом-99W
источник
0

Используйте метод, определенный ниже, чтобы записать данные в файл CSV.

open('outputFile.csv', 'a',newline='')

Просто добавьте дополнительный newline=''параметр внутри openметода:

def writePhoneSpecsToCSV():
    rowData=["field1", "field2"]
    with open('outputFile.csv', 'a',newline='') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(rowData)

Это будет записывать строки CSV без создания дополнительных строк!

Фебин Мэтью
источник
-1

При использовании Python 3 пустых строк можно избежать с помощью модуля кодеков . Как указано в документации, файлы открываются в двоичном режиме, поэтому никаких изменений новой строки kwarg не требуется. Недавно я столкнулся с той же проблемой, и это сработало для меня:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)
JBA
источник