У 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
John Machin


Дивіться відповідь на цю тему: stackoverflow.com/questions/3348460 / ...
Febin Mathew

Відповіді:


887

У Python 2 відкрийте замість outfileрежиму режим . Пише в файл безпосередньо. Якщо ви не відкриєте файл у двійковому режимі, він запишеться, оскільки в текстовому режимі Windows кожен переведе на .'wb''w'csv.writer\r\n\r\r\n\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
Справа в тому, що (як ви маєте на увазі), що немає стандарту. Ця RFE є інформаційною. Хоча \ r \ n може бути "стандартним" для Windows, я впевнений, що програми Unix зазвичай не бачать цього.
Дан Бреслау,

2
@Dan: Це правильно - немає стандарту. Сценарії повинні вказувати lineterminator [повинен був бути названий ROWterminator], який вони хочуть (якщо це не за замовчуванням), і все-таки використовувати двійковий режим, якщо сценарій запускається в Windows, інакше "lineterminator" може бути заповнений.
Джон Махін

8

Примітка. Здається, це не є кращим рішенням через те, як додалася додаткова лінія в системі Windows. Як зазначено в документі python :

Якщо csvfile є файловим об'єктом, його потрібно відкрити прапором 'b' на платформах, де це має значення.

Windows - одна з таких платформ, де це має значення. Хоча зміна лінійного термінатора, як я описав нижче, може усунути проблему, проблему можна було б уникнути взагалі, відкривши файл у двійковому режимі. Можна сказати, що це рішення є більш "елегантним". "Спередання" з лінійним термінатором, швидше за все, призвело б до невідповідного коду між системами в цьому випадку, коли відкриття файлу у двійковому режимі в системі Unix не призводить до ефекту. тобто. це призводить до крос-сумісного коду.

З Документів Python :

У Windows, доданий до режиму 'b', відкриває файл у двійковому режимі, тому існують також такі режими, як 'rb', 'wb' та 'r + b'. Python в Windows робить різницю між текстовими та бінарними файлами; символи кінцевих рядків у текстових файлах автоматично незначно змінюються, коли дані читаються чи записуються. Ця закулісна модифікація файлових даних чудово підходить для текстових файлів ASCII, але вона може пошкодити бінарні дані, такі як у файлах JPEG або EXE. Будьте дуже обережні, використовуючи двійковий режим під час читання та запису таких файлів. У Unix не завадить додавати "b" до режиму, тому ви можете використовувати його платформу незалежно для всіх бінарних файлів.

Оригінал :

Як частина додаткових параметрів для csv.writer, якщо ви отримуєте зайві порожні рядки, можливо, вам доведеться змінити lineterminator (інформація тут ). Приклад нижче адаптований зі сторінки 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' як Outfile:
l --''''''---------------- '' '' ' '' '' '' '27

1
@I__: Ви дійсно повинні почати вивчати документи Python. Дерек дав тобі посилання: docs.python.org/library/csv.html
Dan Breslau

5

Я пишу цю відповідь wrt на 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: працює абсолютно чудово. Проблема вашої відповіді полягає в тому, що тут ви пишете ' 'замість''
Насрін,

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

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 порожніх рядків можна уникнути, використовуючи модуль кодеків . Як зазначено в документації, файли відкриваються у двійковому режимі, тому не потрібно змінювати новий рядок. Я нещодавно стикався з тим самим випуском, який працював на мене:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.