在python中计算30GB + csv文件中双引号外的新行数

Posted

技术标签:

【中文标题】在python中计算30GB + csv文件中双引号外的新行数【英文标题】:Count number of new lines outside double quotes in a 30GB+ csv file in python 【发布时间】:2020-02-24 05:40:42 【问题描述】:

我有一个大文件 (30GB+) csv,我通过逐块解析文件来计算换行符的数量

使用下面的函数

def yieldblocks(file, size=1024*1024):
    while True:
        blocks = file.read(size)
        if not blocks: break
        yield blocks

这样称呼它,

sum(bl.count("\n") for bl in blocks(txtfile))

我可以在一小时内计算换行符(我很惊讶这也是我能得到的最好的)

我的问题是我需要跳过双引号内的新行,因为某些列包含多行内容。

我尝试了以下方法,但它似乎无法正常工作,并且进程退出而没有结果

sum(.5 if re.search('^[^"]*"(?=[^"]*(?:"[^"]*")*[^"]*$).*$', bl) else 1 for bl in yieldblocks(txtfile))

正则表达式是在一行中查找奇数个双引号字符,并且在一个小文件中工作。

我使用的是 2GB RAM,32 位操作系统

注意:我尝试了 CSV 模块,但它比按块计数要慢,我希望我能以某种方式让它工作

【问题讨论】:

如果你使用sum(1 for line in file)会发生什么? 按块计算换行符要慢得多 不想这么说,但这听起来像是 C 的工作。block.count('\n') 方法可能很快,但它不能处理引用。因此,您必须逐个字节地浏览文件,将您在每个点的引号内还是在引号外制表(并在跨块时记住)。这在 Python 中会非常慢。您可能会发现使用内存映射文件会有所帮助。您也可以使用 pandas.read_csv(非常快),可能通过 StringIO 给它提供块。但是你会很难知道在哪里打破这些块(回到寻找不带引号的行尾的原始问题)。 澄清一下:您实际上感兴趣的是文件中的记录数? @mkrieger1 是的,请 【参考方案1】:

这可能对您很有效。 pandas.read_csv 通常非常快,但我还没有尝试过分块。

import pandas as pd
reader = pd.read_csv('file.csv', sep=',', chunksize=10000, low_memory=True)
line_count = sum(len(chunk) for chunk in reader)

the documentation 中有更多信息(不多)。

【讨论】:

谢谢马蒂亚斯。我试过这个。文件中存在一个问题,即在某些行中,列标题的数量与实际内容中的列数不匹配,pandas 不喜欢这样并忽略这些行(如果您提供忽略选项。否则它会一起出错) 这将破坏计算记录数的目的 您可能需要尝试看看是否有办法解决这个问题——也许只需要一列而让它忽略其余的列?否则,您可能只需要逐字节处理整个文件。正如@Danny_ds 指出的那样,这项工作可能受 I/O 限制而不是处理器限制,因此您可以在 Python 中逐字节进行。【参考方案2】:

最简单最快的方法是使用内存映射并按如下方式遍历字节(伪代码):

bool insidequotes = false

for each byte b:
  if b=='"'
    insidequotes = not insidequotes  // false -> true or true -> false

  else if b=='\n' and not insidequotes
    increment recordcount

这应该不会比在磁盘上复制文件(甚至只是读取文件)花费的时间更长 - 不确定 Python 中可能的开销。

这也处理字段内的转义引号:

123,test,"24"" monitor",456

【讨论】:

谢谢丹尼。不起作用,因为我使用的是 32 位操作系统,并且无法映射文件 @QVSJ 也许你可以映射 1GB 的块(不确定 Linux 或 Python)。或者如果这不起作用,只需以二进制模式打开文件并循环遍历它。

以上是关于在python中计算30GB + csv文件中双引号外的新行数的主要内容,如果未能解决你的问题,请参考以下文章

python:如何读取和处理 18GB 的​​ csv 文件? [复制]

hive导入csv文件,字段中双引号内有逗号

Python Pandas:标记数据时出错。 C 错误:读取 1GB CSV 文件时字符串中的 EOF 开始

如何使用 python pandas 在本地系统 Jupyter Notebook 中读取两个较大的 5GB csv 文件?如何在本地加入两个数据框进行数据分析?

通过 NFS 处理 GB 大小的文件时,如何在 Python 中优化文件 I/O?

如何将带有文本信息的 1.3 GB csv 文件读入 Python 的 pandas 对象?