用 Python 编写的 CSV 文件在每行之间有空行

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

但是,当我在 MicrosoftExcel 中打开生成的 csv 时,每条记录后面都有一个额外的空行!

有没有什么办法不让它多写一行空白?

478701 次浏览

注意:这似乎不是首选的解决方案,因为在Windows系统上是如何添加额外的行。如python文档所述:

如果csvfile是一个文件对象,在不同的平台上,它必须用' b '标志打开。

Windows就是这样一个与众不同的平台。虽然按照我下面描述的那样更改行结束符可能已经解决了这个问题,但是通过以二进制模式打开文件可以完全避免这个问题。有人可能会说这种解决方案更“优雅”。在这种情况下,“摆弄”行结束符可能会导致代码在系统之间无法移植,在unix系统上以二进制模式打开文件不会产生任何效果。ie。它产生了跨系统兼容的代码。

从# EYZ0:

在Windows上,'b'附加到模式 以二进制模式打开文件,所以 还有'rb', 'wb', 和“r + b”。Windows上的Python会生成 文本和二进制的区别 文件;中的行尾字符 文本文件会自动更改 在读取或写入数据时略显轻微。 这个幕后修改 文件数据适用于ASCII文本 文件,但它会破坏二进制数据 比如JPEG或EXE文件。是 使用二进制模式时要非常小心 读取和写入此类文件。在 Unix,加个'b'也无妨 切换到模式,这样你就可以使用它了 平台独立的所有二进制文件 文件。< / p >

# EYZ0:

作为csv可选参数的一部分。如果你有额外的空行,你可能需要改变行结束符(info 在这里)。下面的例子改编自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'])

csv.writer模块直接控制行结束符,并直接将\r\n写入文件。在Python 3中,文件必须以未翻译的文本模式打开,参数为'w', newline=''(空字符串),否则它将在Windows上写入\r\r\n,其中默认的文本模式将把每个\n转换为\r\n

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

Python 2中,使用二进制模式打开outfile,模式为'wb',而不是'w',以防止Windows换行符转换。Python 2在Unicode方面也有问题,需要其他变通方法来编写非ascii文本。如果你必须在Python 2上处理将Unicode字符串写入csv,请参阅下面的Python 2链接和页面末尾的UnicodeReaderUnicodeWriter示例,或者查看第三方的unicodecsv模块:

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

文档链接

简单的答案是CSV文件应始终以二进制模式打开无论是用于输入还是输出,否则在Windows上有行结束的问题。具体来说,在输出时,csv模块将写入\r\n(标准的csv行结束符),然后(在文本模式下)运行时将用\r\n (Windows标准行结束符)替换\n,并给出\r\r\n的结果。

摆弄lineterminator不是解决方案。

在Python 3+中,以二进制模式“wb”打开文件将不起作用。或者说,您必须在写入数据之前将其转换为二进制。那只是个麻烦。

相反,您应该将其保持在文本模式,但将换行符重写为空。像这样:

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

我将这个答案w.r.t.写入python 3,因为我最初遇到了相同的问题。

我应该使用PySerial从arduino获取数据,并将它们写入.csv文件中。在我的例子中,每次读取都以'\r\n'结束,因此换行符总是分隔每行。

在我的例子中,newline=''选项不起作用。因为它显示了一些错误,比如:

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


ValueError: illegal newline value: ''

所以他们似乎不接受省略换行符。

只在这里看到一个答案,我提到了writer对象中的行结束符,比如,

# EYZ0

这对我跳过额外的换行很有效。

在使用Python 3时,可以通过使用编解码器模块来避免空行。正如文档中所述,文件是以二进制模式打开的,因此不需要更改换行符kwarg。我最近遇到了同样的问题,这对我来说很有效:

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

使用下面定义的方法将数据写入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

从最初的问题开始的十年里,许多其他的答案都已经过时了。对于Python3,答案就在文档中:

如果csvfile是一个文件对象,它应该用newline=''打开

脚注更详细地解释了:

如果没有指定newline= ",则内嵌在带引号字段中的换行符将不能被正确解释,并且在write时使用\r\n linend的平台上将添加一个额外的\r。指定newline= "应该总是安全的,因为csv模块有自己的(通用的)换行处理。

我使用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)