【问题标题】:Have csv.reader tell when it is on the last line让 csv.reader 告诉它何时在最后一行
【发布时间】:2010-11-01 13:00:21
【问题描述】:

显然,某处的某些 csv 输出实现会从最后一行的右侧截断字段分隔符,并且当字段为空时仅截断文件中的最后一行。

示例输入 csv,字段 'c' 和 'd' 可以为空:

a|b|c|d
1|2||
1|2|3|4
3|4||
2|3

在类似下面的脚本中,我如何判断我是否在最后一行,以便我知道如何适当地处理它?

import csv

reader = csv.reader(open('somefile.csv'), delimiter='|', quotechar=None)

header = reader.next()

for line_num, row in enumerate(reader):
    assert len(row) == len(header)
    ....

【问题讨论】:

  • 请注意,您发布的不是 CSV。 CSV 代表“逗号分隔值” - 分隔符必须是逗号。
  • 大多数 csv 实现允许您指定一个替代字符作为分隔符
  • 唯一接近 CSV 的标准 RFC4180 没有。
  • 在 Python 中,根据 docs.python.org/library/csv.html,“分隔符和引用字符不同”——特别是分隔符不一定是逗号,因此 csv 模块也用于读取“非逗号”分隔值,实际上看起来很荒谬(就像,例如,在 Excel 中,“导出到 CSV”可以使用任何分隔符,具体取决于 Windows 区域设置)。
  • 如果它让任何人感觉更好,我认为可以肯定地说我必须在这里处理的输入不符合任何体面标准。

标签: python csv


【解决方案1】:

基本上你只知道你用完了之后你已经用完了。所以你可以包装 reader 迭代器,例如如下:

def isLast(itr):
  old = itr.next()
  for new in itr:
    yield False, old
    old = new
  yield True, old

并将您的代码更改为:

for line_num, (is_last, row) in enumerate(isLast(reader)):
    if not is_last: assert len(row) == len(header)

等等

【讨论】:

  • 我很惊讶itertools 没有这样的东西。这是一个不断重复出现的用例。
  • 请注意,如果使用 Python 3,则必须将 itr.next() 替换为 next(itr)
【解决方案2】:

我知道这是一个老问题,但我想出的答案与提出的答案不同。 reader 对象在您遍历它时已经增加了 line_num 属性。然后我首先使用row_count 获得总行数,然后将其与line_num 进行比较。

import csv

def row_count(filename):
    with open(filename) as in_file:
        return sum(1 for _ in in_file)

in_filename = 'somefile.csv'
reader = csv.reader(open(in_filename), delimiter='|')

last_line_number = row_count(in_filename)
for row in reader:
    if last_line_number == reader.line_num:
        print "It is the last line: %s" % row

【讨论】:

  • 但您首先要遍历整个文件以获取总行数。效率不是很高。当文件在你第一次和第二次打开之间发生变化时会发生什么?
【解决方案3】:

如果您期望每行中有固定数量的列,那么您应该防范:

(1) ANY 行更短——例如编写器(SQL Server / 查询分析器 IIRC)可能会随机地省略尾随 NULL;用户可以使用文本编辑器修改文件,包括留空行。

(2) ANY 行更长——例如逗号没有正确引用。

您不需要任何花哨的技巧。行读取循环中的一个老式 if 测试:

for row in csv.reader(...):
    ncols = len(row)
    if ncols != expected_cols:
        appropriate_action()

【讨论】:

  • 我同意,但此数据的来源拒绝/太无能,无法向我发送正确格式的数据。我别无选择,只能自己处理它的怪癖。
  • 是的,你必须自己处理它的怪癖,我只是指出应该检查比“最后一行缺少尾随空字段”更多的怪癖,并且可以简单地检查它们而无需花哨代码——我不明白你的“但是”。
【解决方案4】:

如果您想准确获取最后一行,请尝试以下代码:

with open("\\".join([myPath,files]), 'r') as f:
    print f.readlines()[-1] #or your own manipulations

如果您想继续使用行中的值,请执行以下操作:

f.readlines()[-1].split(",")[0] #this would let you get columns by their index

【讨论】:

    【解决方案5】:

    只需将行扩展到表头的长度即可:

    for line_num, row in enumerate(reader):
        while len(row) < len(header):
            row.append('')
        ...
    

    【讨论】:

      【解决方案6】:

      当 csv 阅读器读取最后一行时,你能不能只捕获错误

      尝试: ...在这里做你的事情... 除了:停止迭代

      条件?

      有关如何使用 try:catch:Python CSV DictReader/Writer issues 的示例,请参阅 stackoverflow 上的以下 python 代码

      【讨论】:

      • 当你在最后一行时不会告诉你,只有在你通过最后一行后才会告诉你。
      • 我再次阅读了您的问题,您是对的,这不是您要问的 - 您想要一种处理最后一行的方法。为什么不能使用下面提供的 John Machin 的解决方案?
      【解决方案7】:

      如果您使用for row in reader:,它将在读取最后一项后停止循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        相关资源
        最近更新 更多