2016-07-27 10 views
1

私はこれにsimilar questionを見ましたが、私の苦境は新しい質問を保証するのに十分な方法で違うと思います。なぜPython辞書はあまりにも多くのメモリを使用していますか?

私は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...") 
+0

デフォルトパラメータとして可変オブジェクトを使用しないでください:

はこれを試してみてください。 http://docs.python-guide.org/en/latest/writing/gotchas/ – cdarke

+0

を参照してください。@cdarkeさんのお返事ありがとうございます。理由を詳しく説明してください。私がstruc = {}をインクルードした理由は、たとえば、5つの別々のファイルを開き、それらがすべて同じオブジェクトの別々のブランチの下に格納されるようにするためです。例えばx = {file1:{}、file2:{}} –

+0

各呼び出しは同じ辞書を使用します。私が与えたリンクを読んだ?コンパイル時に空の辞書 '{}'が関数の属性として作成されます。デフォルトを使用して関数を28回呼び出した場合、28種類の辞書は取得されず、すべて同じものを共有します。デフォルト値を 'None'に設定し、関数の本体でその値をテストします。 – cdarke

答えて

2

各呼び出しで同じ辞書が使用されます。 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 
+0

私は今これを修正しましたが、関数の呼び出しがなぜ私に非常に多くのメモリを使用するオブジェクトを与えているのかまだ分かりません。 –

関連する問題