繁体   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