2012-04-09 11 views
6
import os 
import xml.etree.ElementTree as et 

for ev, el in et.iterparse(os.sys.stdin): 
    el.clear() 

ओडीपी संरचना RDF dump पर ऊपर चलने के परिणाम हमेशा स्मृति में वृद्धि करते हैं। ऐसा क्यों है? मैं समझता हूं कि ElementTree अभी भी एक पार्स पेड़ बनाता है, यद्यपि बच्चे नोड्स clear() एड के साथ। यदि यह स्मृति उपयोग पैटर्न का कारण है, तो क्या इसके चारों ओर एक रास्ता है?एलिमेंटट्री.टरपरसे() का उपयोग करते समय मेमोरी उपयोग बढ़ाना चाहिए जब पेड़ को साफ़ करें() पेड़?

+0

कृपया "हमेशा बढ़ते" को स्पष्ट करें। यदि आप ऊपर एक लूप में करते हैं, तो स्मृति उपयोग विस्फोट करता है? या क्या आप केवल एक बार ऐसा करने के बाद उपयोग को देखते हैं, यहां तक ​​कि सभी वस्तुओं को मुक्त करने के बाद भी? – wberry

+0

मेरा मतलब है कि मैं ऊपर के कार्यक्रम के लिए स्मृति उपयोग की अपेक्षा करता हूं। इसके बजाय, यह एक monotic वृद्धि दिखाता है। –

+0

ऊपर लूप में चल रहा है इसका कोई प्रभाव नहीं पड़ता है, क्योंकि यह सिर्फ stdin का उपभोग करेगा। –

उत्तर

8

आप clear प्रत्येक तत्व में हैं लेकिन उनके संदर्भ मूल दस्तावेज़ में रहते हैं। तो व्यक्तिगत तत्व अभी भी कचरा इकट्ठा नहीं किया जा सकता है। ElementTree दस्तावेज़ों में this discussion देखें।

समाधान तो की तरह, जड़ में संदर्भ स्पष्ट करने के लिए है:

# get an iterable 
context = iterparse(source, events=("start", "end")) 

# turn it into an iterator 
context = iter(context) 

# get the root element 
event, root = context.next() 

for event, elem in context: 
    if event == "end" and elem.tag == "record": 
     ... process record elements ... 
     root.clear() 

स्मृति उपयोग है, जो अपनी स्थिति को प्रभावित नहीं किया जा सकता है के बारे में याद करने के लिए एक और बात यह है कि एक बार वीएम ढेर भंडारण के लिए स्मृति आवंटित सिस्टम से, यह आमतौर पर उस स्मृति को कभी वापस नहीं देता है। अधिकांश जावा वीएम इस तरह से काम करते हैं। तो आपको top या ps में दुभाषिया के आकार की अपेक्षा नहीं करना चाहिए, भले ही ढेर स्मृति का उपयोग न किया जाए।

+0

आह, यही वह है जिसे मैं सुनना चाहता था। मैं समझ गया कि ईटी अभी भी एक पेड़ का निर्माण कर रहा था, लेकिन इसके लिए नया होने के कारण, मुझे नहीं पता था कि इसकी जड़ कैसे प्राप्त करें। धन्यवाद! –

0

मैं एक ही मुद्दे में भाग गया। दस्तावेज चीजों को बहुत स्पष्ट नहीं करता है। मेरे मामले में मुद्दा था:

1) कॉलिंग स्पष्ट बच्चों के नोड्स के लिए स्मृति जारी करता है। दस्तावेज़ीकरण कहता है कि यह सभी स्मृति जारी करता है। साफ़ स्मृति को रिलीज़ नहीं करता है जिसके लिए स्पष्ट कहा जाता है, क्योंकि वह स्मृति माता-पिता से संबंधित है जो इसे आवंटित करती है। 2) root.clear() को कॉल करना, जो कि रूट पर निर्भर करता है। यदि रूट माता-पिता है तो यह काम करेगा। अन्यथा, यह स्मृति मुक्त नहीं करेगा।

फ़िक्स माता-पिता का संदर्भ रखना था, और जब हमें अब नोड की आवश्यकता नहीं है, तो हम parent.remove (child_node) को कॉल करते हैं। यह काम करता है और यह कुछ केबीएस में मेमोरी प्रोफाइल रखता है।

1

जैसा कि केविन गुएरा द्वारा दिए गए उत्तर में बताया गया है, ElementTree दस्तावेज़ में "root.clear()" रणनीति केवल रूट के पूरी तरह से पार्स किए गए बच्चों को हटा देती है। अगर वे बच्चे बड़ी शाखाएं लंगर रहे हैं, तो यह बहुत उपयोगी नहीं है।

वह आदर्श समाधान को छुआ, लेकिन किसी भी कोड पोस्ट नहीं किया, इसलिए यहाँ एक उदाहरण है:

element_stack = [] 
context = ET.iterparse(stream, events=('start', 'end')) 
for event, elem in context: 
    if event == 'start': 
     element_stack.append(elem) 
    elif event == 'end': 
     element_stack.pop() 
     # see if elem is one of interest and do something with it here 
     if element_stack: 
      element_stack[-1].remove(elem) 
del context 

ब्याज उसके उप-तत्व की जरूरत नहीं होगी के तत्व; जैसे ही उनके अंतिम टैग देखे गए थे उन्हें हटा दिया जाएगा। यह ठीक हो सकता है यदि आपको केवल तत्व के पाठ या विशेषताओं की आवश्यकता है।

यदि आप तत्व के वंशजों में पूछना चाहते हैं, तो आपको इसके लिए एक पूर्ण शाखा बनाने की आवश्यकता है। इसके लिए, उन तत्वों के लिए गहराई काउंटर के रूप में लागू ध्वज बनाए रखें। गहराई शून्य होने पर केवल .remove() को कॉल करें:

element_stack = [] 
interesting_element_depth = 0 
context = ET.iterparse(stream, events=('start', 'end')) 
for event, elem in context: 
    if event == 'start': 
     element_stack.append(elem) 
     if elem.tag == 'foo': 
      interesting_element_depth += 1 
    elif event == 'end': 
     element_stack.pop() 
     if elem.tag == 'foo': 
      interesting_element_depth -= 1 
      # do something with elem and its descendants here 
     if element_stack and not interesting_element_depth: 
      element_stack[-1].remove(elem) 
del context 
संबंधित मुद्दे