【问题标题】:Writing a .CSV file in Python that works for both Python 2.7+ and Python 3.3+ in Windows在 Python 中编写适用于 Windows 中的 Python 2.7+ 和 Python 3.3+ 的 .CSV 文件
【发布时间】:2015-07-02 15:58:58
【问题描述】:

编辑:我把它放在标题中,但我意识到我没有在正文中提到它。这似乎是特定于 Windows 的。

我很难在适用于 Python 2.7 和 3.3 的脚本中使用 csv Python 模块编写输出。

第一次尝试在 Python 2.7 中按预期工作:

with open('test.csv', 'wb') as csv_file:
    writer = csv.DictWriter(csv_file, ['header1', 'header2'])
    writer.writeheader()
    for item in items:
        writer.writerow(item)

然而,当同样的事情在 Python 3.3 中运行时,你会得到:

TypeError: 'str' does not support the buffer interface

所以我将'wb' 更改为'wt' 并且它运行了,但现在我在文件中每隔一行有一个额外的空白行。

为了解决这个问题,我改变了:

with open('test.csv', 'wt') as csv_file:

到:

with open('test.csv', 'wt', newline='') as csv_file:

但现在,它破坏了 Python 2.7:

TypeError: 'newline' is an invalid keyword argument for this function

我知道我可以这样做:

try:
    with open('test.csv', 'wt', newline='') as csv_file:
        writer = csv.DictWriter(csv_file, ['header1', 'header2'])
        writer.writeheader()
        for item in items:
            writer.writerow(item)
except TypeError:
    with open('test.csv', 'wb') as csv_file:
        writer = csv.DictWriter(csv_file, ['header1', 'header2'])
        writer.writeheader()
        for item in items:
            writer.writerow(item)

但是,这有一些严重的重复。

有人有更清洁的方法吗?

编辑:测试数据很简单,没有换行符或任何东西:

items = [{'header1': 'value', 'header2': 'value2'},
         {'header1': 'blah1', 'header2': 'blah2'}]

【问题讨论】:

  • 你不能用'w'代替'wb''wt'吗?
  • 当您在 Python 2 中运行脚本时,您的 items 列表中的字符串是否为 unicode 字符串?这些值是否总是 ASCII,或者它们是否包含需要编码的额外字符?即使您能够在两个版本的 Python 下运行相同的代码,也可能不会得到相同的结果!
  • @Blckknght - 我将测试数据添加到问题的底部。它只是 ASCII 文本。

标签: python python-2.7 csv python-3.x python-3.3


【解决方案1】:

我尝试了几种方法。据我所知,简单地使用'w' 可能是一个解决方案:

with open('test.csv', 'w') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames=['header1', 'header2'], lineterminator='\n')
    # write something

【讨论】:

  • 如果我这样做,我仍然每隔一行得到空行。您是否在 Windows 或其他设备上尝试过此操作?
  • @Tamerz 您获得了额外的新行,因为您的数据中有额外的新行....strip() 可能是您所需要的。
  • @Tamerz 我尝试了一些假数据,结果很好。所以我认为你的数据也有问题。
  • wwt 相同
  • @skyline75489 - 将测试数据添加到原始问题。你可以看到它只是一个字典中的几个字符串。
【解决方案2】:

这是一个更简单的通用方法:

import sys

if sys.version_info[0] == 2:  # Not named on 2.6
    access = 'wb'
    kwargs = {}
else:
    access = 'wt'
    kwargs = {'newline':''}

with open('test.csv', access, **kwargs) as csv_file:
    writer = csv.DictWriter(csv_file, ['header1', 'header2'])
    writer.writeheader()
    for item in items:
        writer.writerow(item)

这里的原则是不要试图与 Python 2 和 3 之间的差异作斗争,而是要有条件代码。没有这种测试,你只能写这么多代码,迟早你要测试 Python 版本。

【讨论】:

  • 我认为让**kwargs 参与其中可能是一个很好的解决方案。它仍然不漂亮,但比我拥有的所有副本要好得多。这绝对适用于我的场景。谢谢。
  • 我选择了@skyline75489 给出的答案,但我仍然喜欢这个以备将来使用。有时我确实需要这样做,但不知道最好的方法。
  • @Tamerz:查看my answer 类似的问题。它适用于两个版本的 Python 并处理打开文件以进行读取和写入(加上。如open(),如果未明确指定,则默认为读取模式)。它也不需要使用全局变量。
猜你喜欢
  • 1970-01-01
  • 2016-12-15
  • 2015-01-22
  • 2013-07-23
  • 2018-02-11
  • 2014-05-09
  • 2017-09-01
  • 1970-01-01
  • 2017-04-06
相关资源
最近更新 更多