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


445
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时,每条记录后都有一个额外的空白行!

有没有办法使它不放在多余的空白行?


4
请确认在Windows
John Machin 2010年


看到这个线程的答案:stackoverflow.com/questions/3348460/...
Febin马修

Answers:


885

在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.opennewlines参数与一起使用。如果您仍在使用2.x编写,那么无论如何,这似乎是一个更好的选择,因为它是向前兼容的。
jpmc26

@ jpmc26通常,这是一个很好的建议,但是csv模块不能与一起正常使用io.openunicodecsvPython 2.7 有一个更好的第三方模块。
马克·托隆宁'18

知道为什么该newline=''技巧在带有StringIO或TemporaryFile的python3中不起作用吗?
fmoo

@fmoo定义“无效”。他们俩都按照我期望的方式工作。StringIO缓冲将被编码到文件中的相同代码点,并TemporaryFile支持newline参数,因此可以像使用一样打开它open。使用无法正常工作的示例程序提出问题。
Mark Tolonen

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
@丹:我用“标准”作为形容词,而不是名词,意思是“通常”或“普通地方”。如果您想要近似(名词)标准,请阅读tools.ietf.org/html/rfc4180
John Machin

1
重点是(正如您所暗示的)没有标准。该RFE是信息性的。虽然\ r \ n在Windows上可能是“标准”的,但我确信Unix应用程序通常不会那样看。
丹·布雷斯劳

2
@丹:没错-没有标准。脚本应指定所需的换行符[应该已命名为ROWterminator](如果不是默认值),并且如果脚本在Windows上运行,则仍应使用二进制模式,否则可能会塞满“ lineterminator”。
约翰·马钦

8

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

如果csvfile是文件对象,则必须在有区别的平台上使用“ b”标志打开它。

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

Python Docs

在Windows上,附加到模式的'b'以二进制模式打开文件,因此也有'rb','wb'和'r + b'之类的模式。Windows上的Python区分文本文件和二进制文件。当读取或写入数据时,文本文件中的行尾字符会自动更改。对于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'在一个简单的测试中为我工作。
丹·布雷斯劳

我可以这样做吗?使用open('/ pythonwork / thefile_subset11.csv','w'),lineterminator ='\ n'作为输出文件:
l --''''''---------''''' '''''''2010年

1
@I__:您真的应该开始仔细阅读Python文档。Derek给了您链接:docs.python.org/library/csv.html
Dan Breslau 2010年

5

我正在将这个答案写给python 3,因为我最初遇到了同样的问题。

我应该使用来从arduino获取数据PySerial,并将其写入.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')

这对我来说是多余的换行符。


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

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.