Hallo BlackJack,
die Idee mit dem gc-Modul war wirklich gut. Ich habe folgende Passage eingefuegt, um nach jedem Schleifendurchlauf den Zwischenstand zu bekommen:
Code: Alles auswählen
gc.set_debug(gc.DEBUG_LEAK)
gc.collect()
print "gc-check => checked %i, garbage: %i" % (len(gc.get_objects()), len(gc.garbage))
for o in gc.garbage:
print type(o), o
del gc.garbage[:]
fileErrLog.flush()
Wenn ich das ausfuehre, bekomme ich diese Bildschirmausgabe:
<type 'instance'>
<type 'dict'> {'originalEncoding': 'ascii', 'parseOnlyThese': None, 'fromEncoding': None, 'verbose': 0, 'parent': None, 'parserClass': <class BeautifulSoup.BeautifulSoup at 0x402adf90>, 'quoteStack': [], 'nextSibling': None, '_SGMLParser__starttag_text': u'<A HREF="http://...">', 'currentData': [], 'attrs': [], 'offset': 0, 'instanceSelfClosingTags': {None: None}, 'containsSubstitutions': 0, 'convertEntities': None, 'stack': [], 'isSelfClosing': 0, 'previous': u'\n', 'tagStack': [], 'smartQuotesTo': 'html', 'contents': [], 'markupMassage': [(<_sre.SRE_Pattern object at 0x40058b40>, <function <lambda> at 0x402b5578>), (<_sre.SRE_Pattern object at 0x4006c120>, <function <lambda> at 0x402b55c0>)], 'name': u'[document]', 'markup': None, 'nomoretags': 0, 'next': None, 'literal': 0, 'rawdata': u'', 'lasttag': u'a', 'hidden': 1, 'currentTag': , 'previousSibling': None, 'lineno': 1}
<type 'list'> []
<type 'list'> []
<type 'dict'> {None: None}
<type 'list'> []
<type 'list'> []
<type 'list'> []
<type 'list'> []
<class 'BeautifulSoup.NavigableString'>
<type 'dict'> {'nextSibling': None, 'next': None, 'previousSibling': None, 'parent': None, 'previous': None}
Und in errlog bekomme ich 11 collectable Objekte angezeigt (ich denke die da oben). Aber nur, solange die Suche erfolglos war (also heute morgen noch nichts los war). Inzwischen rast eine schier endlose Liste übers Terminal und ich musste abbrechen. Bei dem, was ich sah, handelte es sich um Tags und NaviableStrings (bzw. Listen und Dicts, die wahrscheinlich davon referenziert werden, siehe oben).
Jetzt habe ich es nochmal versucht, ohne gc.set_debug - was ja die Objekte liefern soll, die unreferenziert, aber nicht collectable sind. Jetzt bekomme ich schon einen Wert von 1201 (beim ersten Durchlauf). Beim Folgedurchlauf sind es dann schon 2412.
Fazit: es gibt in meinem Programm offenbar Lecks, die direkt mit den BeautifulSoup Objekten zutun haben.
Aber wie kann ich die Elemente der garbage-Liste manuell freigeben?
Wenn ich es richtig verstanden habe, muss ich das Basisobjekt (BF) finden, dann deren Referenzierer (gc.get_referrers) identifizieren und das Basisobjekt dann aus all diesen Listen, Dictionaries, Instanzen ... entfernen? Gibt es dafür schon einen Präzedenzfall?
[EDIT] Die BF-Klasse hat keine __del__ Methode, deshalb sollte sie in der Liste nicht abräumbarer Objekte nur auftauchen, weil sie selbst referenziert wird. Dabei ist mit dieses erste Instanzobjekt verdächtig, das ich nicht zuordnen kann. Ich versuche gerade herauszufinden, was das für eine Instanz ist...[/EDIT]
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...