【问题标题】:How to fix memory error while importing a very large csv file to mongodb in python?如何在 python 中将非常大的 csv 文件导入 mongodb 时修复内存错误?
【发布时间】:2022-01-15 10:24:49
【问题描述】:

下面给出了将管道分隔的 csv 文件导入到 monogdb 的代码。

import csv
import json
from pymongo import MongoClient

url = "mongodb://localhost:27017"
client = MongoClient(url)
db = client.Office
customer = db.Customer
jsonArray = []

with open("Names.txt", "r") as csv_file:
    csv_reader = csv.DictReader(csv_file, dialect='excel', delimiter='|', quoting=csv.QUOTE_NONE)
    for row in csv_reader:
        jsonArray.append(row)
    jsonString = json.dumps(jsonArray, indent=1, separators=(",", ":"))
    jsonfile = json.loads(jsonString)
    customer.insert_many(jsonfile)

以下是我在运行上述代码时遇到的错误。

Traceback (most recent call last):
  File "E:\Anaconda Projects\Mongo Projects\Office Tool\csvtojson.py", line 16, in <module>
    jsonString = json.dumps(jsonArray, indent=1, separators=(",", ":"))
  File "C:\Users\Predator\anaconda3\lib\json\__init__.py", line 234, in dumps
    return cls(
  File "C:\Users\Predator\anaconda3\lib\json\encoder.py", line 201, in encode
    chunks = list(chunks)
MemoryError

如果在 for 循环下用一些缩进修改代码。 MongoDB 会再次导入相同的数据,而不会停止。

import csv
import json
from pymongo import MongoClient

url = "mongodb://localhost:27017"
client = MongoClient(url)
db = client.Office
customer = db.Customer
jsonArray = []

with open("Names.txt", "r") as csv_file:
    csv_reader = csv.DictReader(csv_file, dialect='excel', delimiter='|', quoting=csv.QUOTE_NONE)
    for row in csv_reader:
        jsonArray.append(row)
        jsonString = json.dumps(jsonArray, indent=1, separators=(",", ":"))
        jsonfile = json.loads(jsonString)
        customer.insert_many(jsonfile)

【问题讨论】:

  • 使用mongoimport 可能是更好的选择。注意,mongoimport 也接受来自 STDIN 的输入,您可以在 python 中转换行然后打印到 STDIN 而不是编写单独的文件。
  • 我不懂python但可能像if (row % 1000 == 0) customer.insert_many(jsonfile)这样插入,即1000个批量插入文档
  • @Wernfried Domscheit 这是结果` Traceback(最近一次调用最后一次):文件“E:\Anaconda Projects\Mongo Projects\SDR Tool\csvtojson.py”,第 18 行,在 if row % 1000 == 0: TypeError: unsupported operand type(s) for %: 'dict' and 'int' `
  • 您能否添加一个文件格式的小样本 - 仅 3 或 4 行
  • ^^ 加上一个标题行(如果有的话)

标签: python json pandas mongodb csv


【解决方案1】:

我建议你使用 pandas;它通过设置 chunksize 参数来提供"chunked" mode,您可以根据内存限制进行调整。 insert_many() 效率也更高。

加上代码变得更加简单:

import pandas as pd
filename = "Names.txt"

with pd.read_csv(filename, chunksize=1000, delimiter='|') as reader:
    for chunk in reader:
        db.mycollection.insert_many(chunk.to_dict('records'))

如果您发布文件示例,我可以更新以匹配。

【讨论】:

  • 文件“C:\Users\Predator\anaconda3\lib\site-packages\pandas\io\parsers\python_parser.py”,第 722 行,_alert_malformed 引发 ParserError(msg) pandas.errors。 ParserError:预计第 117143 行有 48 个字段,看到 49
  • Given 下面是我使用的代码。 with pd.read_csv(csv_file, chunksize=1000, delimiter='|', engine='python', encoding='latin-1', quoting=csv.QUOTE_NONE) as reader: for chunk in reader:
  • 如果没有文件示例,我真的无能为力。
  • 这个错误也很简单——标题中有 48 个字段,一行有 49 个条目。
  • 这是因为某些文本之间可能插入了逗号。
【解决方案2】:

一次插入一条记录可以解决内存问题。

import csv
import json

from pymongo import MongoClient

url_mongo = "mongodb://localhost:27017"
client = MongoClient(url_mongo)
db = client.Office
customer = db.Customer
jsonArray = []
file_txt = "Text.txt"
rowcount = 0
with open(file_txt, "r") as txt_file:
    csv_reader = csv.DictReader(txt_file, dialect="excel", delimiter="|", quoting=csv.QUOTE_NONE)
    for row in csv_reader:
        rowcount += 1
        jsonArray.append(row)
    for i in range(rowcount):
        jsonString = json.dumps(jsonArray[i], indent=1, separators=(",", ":"))
        jsonfile = json.loads(jsonString)
        customer.insert_one(jsonfile)
print("Finished")

感谢大家的想法

【讨论】:

    猜你喜欢
    • 2013-05-17
    • 2014-03-02
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 2012-01-09
    • 1970-01-01
    • 2018-05-27
    相关资源
    最近更新 更多