【问题标题】:Why does python dictionary use so much memory?为什么python字典使用这么多内存?
【发布时间】:2016-12-01 16:13:02
【问题描述】:

我见过similar question 对此,但我认为我的困境在足以保证一个新问题的方式上有所不同。

我创建了一个函数,它打开一个 csv 文件并根据维度和指标列表将数据聚合到一个类似 json 的字典结构中。

问题是当我用它打开一个 0.97GB 的文件时,当我查看我的进程时,python 进程正在使用大约 1.02GB 的内存。请记住,我只选择文件中的一小部分字段,并且数据是聚合的,我认为它本质上应该更小。此外,字典变量是从函数返回的唯一东西,所以这不应该意味着它是函数运行后唯一留在内存中的东西吗?有谁知道为什么我的字典对象使用这么多内存?

**EDIT - 我也理解 csv.reader() 是一个生成器,所以我什至不会一次加载整个文件,所以它必须只是使用所有内存的字典对象?

我在 Windows 上使用 Python 2.7。

import json
import inspect
from pprint import pprint
import csv
from datetime import datetime
import sys


def jsonify_csv(fileString, dimensions, metrics, struc = {}):
    with open(fileString, 'rb') as f:
        reader=csv.reader(f)
        headings = reader.next()
        i = 0
        for line in reader:
            i+=1
            row =  {headings[i]:v for i, v in enumerate(line)}
            pointer = struc
            for dimension in dimensions:
                if dimension == 'date':
                    val = str(datetime.strptime(row[dimension], "%d/%m/%Y").date().month)
                else:
                    val = str(row[dimension])
                pointer.setdefault(val, {})
                pointer = pointer[val]
            for metric in metrics:
                pointer.setdefault(metric, 0.0)
                try:
                    pointer[metric] += float(row[metric])
                except ValueError:
                    pass
    return struc


start = datetime.today()

dims = ['brand', 'source', 'affiliate', 'country', 'store', 'salesbundle', 'product', 'ordertype', 'returncode', 'supplier', 'category']

metrics = ['sales', 'qty', 'cogs', 'carriagereclaim', 'Carriage Charged Carrier', 'carriage_est', 'mktg_est', 'mktg_cost', 'royalty', 'finance', 'scrap_cost', 'mp_cost', 'budgetsales', 'budgetcosts', 'BSTD', 'budgetaftersales', 'budgetscrap', 'budgetcarriagerecovery', 'budgetcarriagepaid', 'budgetmetapack', 'budgetmarketing', 'budgetaffiliate', 'budgetoffline', 'budgetroyalty', 'budgetfinance', 'bundle_qty', 'misc_adjustments']

jsonified = jsonify_csv('PhocasSales_2015+.csv', dims, metrics)

print 'file opened', datetime.today()-start

stop = raw_input("waiting...")

【问题讨论】:

  • 不要使用可变对象作为默认参数。见docs.python-guide.org/en/latest/writing/gotchas
  • 嗨@cdarke 感谢您的回答,请您详细说明原因?我包含 struc = {} 的原因是我想打开 5 个单独的文件并将它们全部存储在同一对象的不同分支下。例如x = {file1:{},file2:{}}
  • 每次调用都将使用同一个字典。你读过我给的链接吗?空字典{} 在编译时创建为函数的属性。如果您使用默认值调用该函数 28 次,您将不会获得 28 个不同的字典,它们将共享同一个字典。默认为None,然后在函数体中测试它的值。
  • @cdarke 抱歉,我没有看到您提供的链接,谢谢。我从默认参数更改它并在我调用函数时传递 {}
  • 或默认为无!谢谢

标签: python csv dictionary memory


【解决方案1】:

每次调用都将使用相同的字典。见http://docs.python-guide.org/en/latest/writing/gotchas/。空字典{} 在编译时创建为函数的属性。

如果您使用默认值调用该函数 28 次,您将不会得到 28 个不同的字典,它们将共享同一个字典。默认为 None 然后在函数体中测试它的值。

试试这个:

def jsonify_csv(fileString, dimensions, metrics, struc = None):
    if struc is None:
        struc = {}

    with open(fileString, 'rb') as f:
    ... # and so on

【讨论】:

  • 我现在已经解决了这个问题,但仍然不确定为什么单次调用该函数会给我一个使用这么多内存的对象。
猜你喜欢
  • 2013-06-06
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多