【问题标题】:Python CSV parsing fills up memoryPython CSV 解析填满内存
【发布时间】:2015-04-23 06:14:10
【问题描述】:

我有一个包含超过一百万行的 CSV 文件,我正在尝试解析该文件并将这些行插入数据库。

    with open(file, "rb") as csvfile:

        re = csv.DictReader(csvfile)
        for row in re:
        //insert row['column_name'] into DB

对于小于 2 MB 的 csv 文件,这很有效,但除此之外的任何内容最终都会占用我的内存。这可能是因为我将 Dictreader 的内容存储在一个名为“re”的列表中,它无法遍历如此庞大的列表。我肯定需要访问带有列名的 csv 文件,这就是我选择 dictreader 的原因,因为它很容易提供对我的 csv 文件的列级访问。谁能告诉我为什么会发生这种情况以及如何避免这种情况?

【问题讨论】:

  • 虽然没有回答您的实际问题,但如果您需要按原样加载数据,使用数据库自​​己的设施可能会更容易和更快(例如,Postgres 中的COPY table(col1, col2) FROM file WITH CSVLOAD DATA INFILE在 MySQL 中)。

标签: python csv memory


【解决方案1】:

DictReader 不会将整个文件加载到内存中,而是按块读取它,如 DhruvPathak 建议的this answer 中所述。

但是根据您的数据库引擎,磁盘上的实际写入可能仅在提交时发生。这意味着数据库(而不是 csv 阅读器)将所有数据保存在内存中并最终耗尽它。

因此,您应该尝试提交每条n 记录,n 通常在 10 到 1000 之间,具体取决于行的大小和可用内存。

【讨论】:

  • 所以我猜是 SQLAlchemy 正在吞噬我的记忆
  • @Tania :尝试提交每个第 n 条语句,您将得到确认 :-)
  • 是的,我试过了。看起来那是我的问题。有什么办法可以避免?
【解决方案2】:

如果您不需要一次使用整个列,您可以像阅读文本文件一样简单地逐行读取文件并解析每一行。确切的解析取决于您的数据格式,但您可以执行以下操作:

delimiter = ','
with open(filename, 'r') as fil:
    headers = fil.next()
    headers = headers.strip().split(delimiter)
    dic_headers = {hdr: headers.index(hdr) for hdr in headers}
    for line in fil:
        row = line.strip().split(delimiter)
        ## do something with row[dic_headers['column_name']]

这是一个非常简单的示例,但可以更详细。例如,如果您的数据包含 ,,则此方法不起作用。

【讨论】:

  • 你能告诉我我之前代码中的哪一行同时包含所有列吗?
  • AFAIK csv 阅读器在内部已经迭代了行并且不会将所有文件加载到内存中,所以我非常怀疑这是否真的解决了 OP 的问题
  • 我刚刚看到并连根拔起你的答案。我们每天都在学习。
  • headers = headers.strip().split(delimiter) 导致错误 built_in_method has no attr split
  • @Tania 正如 DhruvPathak 和 Serge Ballesta 所建议的那样,这很可能无法解决您的内存错误,因为DictReader 不会将整个文件放入内存
猜你喜欢
  • 2016-10-15
  • 2023-04-03
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2016-03-12
  • 2012-08-31
相关资源
最近更新 更多