【问题标题】:Iterate from a certain row of a csv file in Python从Python中的csv文件的某一行迭代
【发布时间】:2016-06-27 22:45:28
【问题描述】:

我有一个包含数百万行的 csv 文件。我想从 10,000,000 行开始迭代。目前我有代码:

    with open(csv_file, encoding='UTF-8') as f: 
        r = csv.reader(f)
        for row_number, row in enumerate(r):    
            if row_number < 10000000:
                continue
            else:
                process_row(row)      

这可行,但是需要几秒钟才能运行感兴趣的行。大概所有不需要的行都不必要地加载到 python 中,减慢了它的速度。有没有办法在某一行开始迭代过程 - 即没有开始读入的数据。

【问题讨论】:

  • 有什么理由不能使用tail 跳过前 N 行并将其通过管道传输到您的 python 脚本?
  • 旁注:您想将newline='' 传递给open 调用; csv 模块希望您将换行插值留给它,您不希望 open 执行换行符。

标签: python python-3.x csv


【解决方案1】:

你可以使用islice:

from itertools import islice

with open(csv_file, encoding='UTF-8') as f:
    r = csv.reader(f)
    for row in islice(r,  10000000, None):
            process_row(row)  

它仍然会遍历所有行,但效率更高。

您也可以使用consume recipe,它调用以C 速度使用迭代器的函数,在文件对象上调用它你将它传递给 csv.reader,因此您还可以避免使用阅读器不必要地处理这些行:

import collections
from itertools import islice
def consume(iterator, n):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)


with open(csv_file, encoding='UTF-8') as f:
    consume(f, 9999999)
    r = csv.reader(f)
    for row  in r:
          process_row(row)  

正如 Shadowranger 评论的那样,如果文件可以包含嵌入的换行符,那么您将不得不使用阅读器并传递 newline="" 但如果不是这种情况,则使用确实使用文件对象,因为性能差异将是相当大的,特别是如果你有很多列。

【讨论】:

  • 如果字段可能包含嵌入的换行符(即使不是所有的 CSV 方言也是合法的),则不应在原始文件句柄上运行 consume。在 csv.reader 换行之前跳过意味着您会将字段嵌入的换行符错误地解释为记录分隔符。
  • @ShadowRanger,是的,我添加了一条注释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
相关资源
最近更新 更多