簡體   English   中英

CSV 用Python寫的文件每行之間有空行

[英]CSV file written with Python has blank lines between each row

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

但是,當我在Microsoft Excel中打開結果csv時,每條記錄后面多了一個空行!

有沒有辦法讓它不放一個額外的空行?

在Python 2,開放outfile與模式'wb'而不是'w' csv.writer\\r\\n寫入文件。 如果您不以二進制模式打開文件,它將寫入\\r\\r\\n因為在 Windows文本模式下會將每個\\n轉換為\\r\\n

在 Python 3 中,所需的語法發生了變化(請參閱下面的文檔鏈接),因此使用附加參數newline='' (空字符串)打開outfile

例子:

# 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)

文檔鏈接

以二進制模式“wb”打開文件在 Python 3+ 中不起作用。 或者更確切地說,您必須在寫入數據之前將數據轉換為二進制文件。 那只是個麻煩事。

相反,您應該將其保持在文本模式,但將換行符覆蓋為空。 像這樣:

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

簡單的答案是csv 文件應該始終以二進制模式打開,無論是輸入還是輸出,否則在 Windows 上會出現行尾問題。 具體上輸出csv模塊將寫\\r\\n (標准CSV行終止),然后(在文本模式)運行時將取代\\n\\r\\n (Windows標准線路終端),得到的結果\\r\\r\\n

擺弄lineterminator不是解決方案。

注意:這似乎不是首選的解決方案,因為在 Windows 系統上如何添加額外的行。 python文檔中所述

如果 csvfile 是文件對象,則必須在有區別的平台上使用 'b' 標志打開它。

Windows 就是一個這樣的平台,它會有所作為。 雖然如下所述更改行終止符可能已經解決了問題,但可以通過以二進制模式打開文件來完全避免該問題。 有人可能會說這個解決方案更“優雅”。 在這種情況下,“擺弄”行終止符可能會導致系統之間的代碼不可移植,在這種情況下,在 unix 系統上以二進制模式打開文件不會產生任何效果。 IE。 它導致跨系統兼容的代碼。

來自Python 文檔

在 Windows 上,附加到模式的 'b' 以二進制模式打開文件,因此還有像 'rb'、'wb' 和 'r+b' 這樣的模式。 Windows 上的 Python 區分文本文件和二進制文件; 讀取或寫入數據時,文本文件中的行尾字符會自動稍微改變。 這種對文件數據的幕后修改適用於 ASCII 文本文件,但它會破壞 JPEG 或 EXE 文件中的二進制數據。 讀寫此類文件時要非常小心地使用二進制模式。 在 Unix 上,將 'b' 附加到模式並沒有什么壞處,因此您可以獨立於平台對所有二進制文件使用它。

原文

作為 csv.writer 的可選參數的一部分,如果您得到額外的空行,您可能需要更改換行符(此處的信息)。 下面的示例改編自 python 頁面csv 文檔。 將它從 '\\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'])

自原始問題以來的十年中,許多其他答案已經過時。 對於 Python3,文檔中的答案是正確的:

如果 csvfile 是文件對象,則應使用newline=''打開

腳注更詳細地解釋了:

如果未指定 newline='',則嵌入在引用字段中的換行符將不會被正確解釋,並且在寫入時使用 \\r\\n linendings 的平台上將添加一個額外的 \\r。 指定 newline='' 應該始終是安全的,因為 csv 模塊執行自己的(通用)換行處理。

我正在將這個答案寫到 python 3,因為我最初遇到了同樣的問題。

我應該使用PySerial從 arduino 獲取數據,並將它們寫入 .csv 文件中。 在我的案例中,每次閱讀都以'\\r\\n'結束,所以換行符總是分隔每一行。

就我而言, newline=''選項不起作用。 因為它顯示了一些錯誤,例如:

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

ValueError: illegal newline value: ''

所以看起來他們不接受這里省略換行符。

只看到這里的答案之一,我在 writer 對象中提到了行終止符,例如,

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

這對我有用,可以跳過額外的換行符。

使用下面定義的方法將數據寫入 CSV 文件。

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

只需在open方法中添加一個額外的newline=''參數:

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

這將寫入 CSV 行而不創建額外的行!

with open(destPath+'\\'+csvXML, 'a+') as csvFile:
    writer = csv.writer(csvFile, delimiter=';', lineterminator='\r')
    writer.writerows(xmlList)

"lineterminator='\\r'" 允許傳遞到下一行,兩行之間沒有空行。

借用這個答案,似乎最干凈的解決方案是使用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

我用過writerow

def write_csv(writer, var1, var2, var3, var4):
    """
    write four variables into a csv file
    """
    writer.writerow([var1, var2, var3, var4])      
        
numbers=set([1,2,3,4,5,6,7,2,4,6,8,10,12,14,16])
rules = list(permutations(numbers, 4))
#print(rules)
selection=[]
with open("count.csv", 'w',newline='') as csvfile:
    writer = csv.writer(csvfile)

    for rule in rules:
        number1,number2,number3,number4=rule
        if ((number1+number2+number3+number4)%5==0):
            #print(rule)
            selection.append(rule)
            write_csv(writer,number1,number2,number3,number4)

使用 Python 3 時,可以使用codecs模塊避免空行。 如文檔中所述,文件以二進制模式打開,因此無需更改換行符 kwarg。 我最近遇到了同樣的問題,這對我有用:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM