पाइथन में बड़ी डिक्ट्स का उपयोग कैसे करें जो स्मृति में फिट नहीं है? - अजगर, स्मृति, डेटा संरचनाएं, शब्दकोश

हम एक का उपयोग करते हैं dict जिसमें डेटा प्रोसेसिंग के लिए लगभग 4 जीबी डेटा है। यह सुविधाजनक और तेज़ है।

हम जो समस्या कर रहे हैं वह यह है dict 32 जीबी से अधिक हो सकता है।

मैं एक का उपयोग करने के लिए एक रास्ता तलाश रहा हूँ dict (बस एक चर के साथ प्राप्त करें () - विधि आदि) जो उपलब्ध स्मृति से बड़ा हो सकता है। अगर यह अच्छा होगा dict किसी भी तरह डिस्क पर डेटा संग्रहीत किया और डिस्क से डेटा पुनर्प्राप्त किया get(key) कहा जाता है और के लिए मूल्य है key स्मृति में नहीं है

अधिमानतः मैं एक एसक्यूएल डेटाबेस की तरह बाहरी सेवा का उपयोग नहीं करना चाहूंगा।

मुझे मिला टांड़, लेकिन ऐसा लगता है कि स्मृति भी चाहिए।

इस समस्या से कैसे संपर्क करें इस पर कोई विचार?

उत्तर:

जवाब के लिए 3 № 1

ऐसा लगता है कि आप एक कुंजी-मूल्य-स्टोर का उपयोग कर सकते हैं जो वर्तमान में नो-एसक्यूएल के buzzword के तहत प्रचारित है। उदाहरण के लिए, इसके बारे में अच्छी शुरुआत मिल सकती है

http://ayende.com/blog/4449/that-no-sql-thing-key-value-stores

यह आपके द्वारा वर्णित एपीआई के साथ बस एक डेटाबेस है।


उत्तर № 2 के लिए 1

यदि आप SQL डेटाबेस का उपयोग नहीं करना चाहते हैं (जो इस तरह की किसी समस्या का उचित समाधान है) तो आपको या तो उस डेटा को संपीड़ित करने का तरीका पता लगाना होगा जिसका आप काम कर रहे हैं या उपयोग कर रहे हैं इस तरह की एक पुस्तकालय (या अपना खुद का) खुद को डिस्क करने के लिए मैपिंग करने के लिए।

आप भी देख सकते हैं यह प्रश्न कुछ और रणनीतियों के लिए।


उत्तर № 3 के लिए 1

उपयोग अचार शब्दकोश को डिस्क पर क्रमबद्ध करने के लिए मॉड्यूल।फिर शब्दकोश के पुनरावर्तक से लगातार मूल्य लें और शुरुआत में, उन्हें अपने कैश में रखें। फिर एलआरयू जैसे कैश योजना को लागू करें; शब्दकोशों की 'popitem () विधि का उपयोग करके एक शब्दकोश वस्तु को हटाएं और एलआरयू के मामले में पहले से एक्सेस की गई वस्तु जोड़ें।


उत्तर के लिए 1 № 4

मैं ऐसा करने के लिए किसी भी (तेज़) मॉड्यूल को नहीं ढूंढ पाया और अपना खुद का निर्माण करने का फैसला किया (मेरा पहला पायथन प्रोजेक्ट - धन्यवाद @ ब्लब्बर कुछ विचारों के लिए: पी)। आप इसे गिटहब पर पा सकते हैं: https://github.com/ddofborg/diskdict टिप्पणियाँ स्वागत है!


जवाब के लिए 0 № 5

/ संपादित करें: यह अब एक पायथन मॉड्यूल है: fdict

मेरे पास एक समान मुद्दा था लेकिन मैं नेस्टेड डिक्ट्स पर काम कर रहा था। मेरे डेटासेट की बहुत घोंसला वाली प्रकृति के कारण, सभी उपलब्ध समाधान मेरे उपयोग के मामले में फिट नहीं होंगे: shelve, chest, shove, sqlite, zodb, और जब भी आप कोई अन्य नोएसक्यूएल डीबी काम करते हैंएक स्तर है, क्योंकि वे डेटाबेस में क्रमबद्ध करने के लिए सभी अचार / JSON मान हैं, इसलिए पहले स्तर के बाद सभी मानों को क्रमबद्ध किया गया है और नेस्टेड ऑब्जेक्ट्स के बढ़ते अपडेट करना संभव नहीं है (आपको पूरी शाखा को पहले से लोड करना होगा -वेल नोड, संशोधित करें, और फिर इसे वापस रखें), जो संभव नहीं है यदि आपके घोंसले की वस्तुएं स्वयं ही बड़ी हों।

इसका अर्थ यह है कि इन समाधानों में मदद मिलेगी जब आपके पास बहुत से प्रथम-स्तर के नोड्स हों, लेकिन जब आपके पास पहले चरण-स्तर नोड्स और गहरे पदानुक्रम नहीं होते हैं।

इसका मुकाबला करने के लिए, मैंने मूल पायथन स्कूल पर एक कस्टम श्रद्धांजलि अर्पित की है, आंतरिक रूप से घोंसला वाले रूप में घोंसला वाले नियम का प्रतिनिधित्व करने के लिए: dict()["a"]["b"] आंतरिक रूप से प्रतिनिधित्व किया जाएगा dict()["a/b"]

फिर इस "आंतरिक रूप से चपटे" निर्देश के शीर्ष पर, अब आप डिस्क समाधान के लिए किसी ऑब्जेक्ट का उपयोग कर सकते हैं shelve, जो मैंने उपयोग किया लेकिन आप आसानी से किसी और चीज़ के साथ प्रतिस्थापित कर सकते हैं।

यहां कोड है:

import shelve

class fdict(dict):
"""Flattened nested dict, all items are settable and gettable through ["item1"]["item2"] standard form or ["item1/item2"] internal form.
This allows to replace the internal dict with any on-disk storage system like a shelve"s shelf (great for huge nested dicts that cannot fit into memory).
Main limitation: an entry can be both a singleton and a nested fdict, and there is no way to tell what is what, no error will be shown, the singleton will always be returned.
"""
def __init__(self, d=None, rootpath="", delimiter="/", *args):
if d:
self.d = d
else:
self.d = {}
self.rootpath = rootpath
self.delimiter = delimiter

def _buildpath(self, key):
return self.rootpath+self.delimiter+key if self.rootpath else key

def __getitem__(self, key):
# Node or leaf?
if key in self.d: # Leaf: return the value
return self.d.__getitem__(key)
else: # Node: return a new full fdict based on the old one but with a different rootpath to limit the results by default
return fdict(d=self.d, rootpath=self._buildpath(key))

def __setitem__(self, key, value):
self.d.__setitem__(self._buildpath(key), value)

def keys(self):
if not self.rootpath:
return self.d.keys()
else:
pattern = self.rootpath+self.delimiter
lpattern = len(pattern)
return [k[lpattern:] for k in self.d.keys() if k.startswith(pattern)]

def items(self):
# Filter items to keep only the ones below the rootpath level
if not self.rootpath:
return self.d.items()
else:
pattern = self.rootpath+self.delimiter
lpattern = len(pattern)
return [(k[lpattern:], v) for k,v in self.d.items() if k.startswith(pattern)]

def values(self):
if not self.rootpath:
return self.d.values()
else:
pattern = self.rootpath+self.delimiter
lpattern = len(pattern)
return [v for k,v in self.d.items() if k.startswith(pattern)]

def update(self, d2):
return self.d.update(d2.d)

def __repr__(self):
# Filter the items if there is a rootpath and return as a new fdict
if self.rootpath:
return repr(fdict(d=dict(self.items())))
else:
return self.d.__repr__()

def __str__(self):
if self.rootpath:
return str(fdict(d=dict(self.items())))
else:
return self.d.__str__()

class sfdict(fdict):
"""A nested dict with flattened internal representation, combined with shelve to allow for efficient storage and memory allocation of huge nested dictionnaries.
If you change leaf items (eg, list.append), do not forget to sync() to commit changes to disk and empty memory cache because else this class has no way to know if leaf items were changed!
"""
def __init__(self, *args, **kwargs):
if not ("filename" in kwargs):
self.filename = None
else:
self.filename = kwargs["filename"]
del kwargs["filename"]
fdict.__init__(self, *args, **kwargs)
self.d = shelve.open(filename=self.filename, flag="c", writeback=True)

def __setitem__(self, key, value):
fdict.__setitem__(self, key, value)
self.sync()

def get_filename(self):
return self.filename

def sync(self):
self.d.sync()

def close(self):
self.d.close()

दोनों fdict तथा sfdict मानक की तरह प्रयोग योग्य हैं dict (लेकिन मैंने सभी विधियों को लागू नहीं किया है)।

पूरा कोड यहां है: https://gist.github.com/lrq3000/8ce9174c1c7a5ef546df1e1361417213

यह एक पूर्ण पायथन मॉड्यूल में आगे विकसित किया गया था: fdict

बेंचमार्किंग के बाद, अप्रत्यक्ष पहुंच का उपयोग करते समय यह लगभग 10x धीमी गति से है (यानी, x["a"]["b"]["c"]), और प्रत्यक्ष पहुंच का उपयोग करते समय तेज़ी से (यानी, x["a/b/c"]), हालांकि यहां मैं ओवरहेड के लिए जिम्मेदार नहीं हूं shelve एक को बचाने के लिए anydbm फ़ाइल, बस के fdict डेटा संरचना की तुलना में dict


संबंधित सवाल
सबसे लोकप्रिय