Garbage Collection selbst gemacht - module löschen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Dienstag 13. Januar 2009, 12:28

Hallo zusammen,

ich habe ein Programm, dass eine große XML Datei parst und als Sqlite speichert. Während des Parsens bläht sich der Speicherbedarf des Programmes auf > 200 MB auf, die danach nicht freigegeben werden.

Zuerst dachte ich, es reicht, wenn ich mit del die großen Arrays lösche - dadurch wird aber der Speicher nicht freigegeben. Da das Parsen in einem Submodul geschieht, wollte ich dann nach dem Parsen das Modul löschen - das scheint aber nicht möglich zu sein. Ich habe das Problem mal auf folgendes Beispiel runtergebrochen:

Code: Alles auswählen

#!/usr/bin/env python
import math

class tst():
    def __init__(self):
            pass
    def run(self):
            x = math.floor(10.435)
            print x
            del x, math
tst().run()
Anscheinend ist das überhaupt nicht möglich?! Ich muss meine Klasse aber irgendwie aus dem Speicher löschen, weil sie einfach zu viele Ressourcen frisst.

Vielen Dank schonmal für Hinweise!

Daniel
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Dienstag 13. Januar 2009, 13:10

Ich kann dein Problem nicht nachvollziehen.
Was soll das gezeigte Codesnippet denn bewirken?
Nach meiner Erfahrung funktioniert die Garbage Collection von Python eigentlich sehr zuverlässig. Und zwar immer dann es es keine Refernz
mehr auf ein Objekt gibt.
Was ist das denn für ein Submodul was du zum parsen verwendest?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Dienstag 13. Januar 2009, 13:22

Dein Problem wird nichts mit Modulen zu tun haben, sondern mit a) der verwendeten XML-Bibliothek oder b) mit sqlite. Sollte eine dieser Bibliotheken die Eigenschaft haben, einmal reservierten Speicher nicht wieder freizugeben, kannst du wenig machen.

Für XML gilt ansonsten der übliche Tipp, lade nicht alles und bearbeite es im Hauptspeicher, sondern streame es, auch wenn dann die Verarbeitung komplizierter wird (SAX vs. DOM API ist hier das Stichwort).

Stefan
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Dienstag 13. Januar 2009, 13:51

hallo sma,

dadurch würde aber die Verarbeitung wahrscheinlich länger dauern - zur Zeit wird das ganze mit einem Rutsch in die DB geschrieben. Ich glaube auch nicht, dass das Problem bei XML liegt sondern darin, dass ich entsprechend große Variabeln erstelle. Es muss doch aber möglich sein, die wieder zu löschen?

@Zap:
es ist ein selbstprogrammiertes Modul, das xml.sax verwendet. Der große Speicherverbrauch resultiert aus Arrays mit insgesamt ca. 300000 Feldern. Wenn ich dieses Modul einbinde, die darin enthaltene Klasse lade und danach die Klasse wieder lösche, müsste doch der Speicher frei gegeben werden?
Der Codeschnippsel soll verdeutlichen, dass es nicht möglich ist, Module mit del zu entladen, weil Python da wohl irgendeine Art Vorausschau betreibt. Sprich: Der Snippet funktioniert nicht, sollte es m.E. aber.

Übrigens: Die Klasse, die ich einbinde und die soviel Speicher verbraucht, lösche ich im Code auch wieder mit del - wenn die Garbage Collection funktionieren würde, müsste spätestens hier der Speicher wieder frei gegeben werden.

Gruß,

brb
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Dienstag 13. Januar 2009, 13:57

Du kannst gc importieren und ihn zwingen einzusammeln... Aber das funktioniert natürlich auch nicht 100% :3 Auf einen GC kann man sich nicht sooooo verlassen. Es dauert halt seine Zeit, bis alles aufgesammeln ist... Falls dir Speicher so wichtig ist, solltest du kleine Teile zuerst verarbeiten lassen oder darüber nachdenken andere Bibliotheken zu benutzen...

LXML ist für XML ganz toll, vielleicht löst das dein Problem ja schon magisch :)
Benutzeravatar
bwbg
User
Beiträge: 381
Registriert: Mittwoch 23. Januar 2008, 13:35

Dienstag 13. Januar 2009, 14:16

"del" löscht nur die Referenz auf ein Objekt, welches dann, wenn es keine Referenzen mehr aufweist (hoffentlich) vom GC eingesammelt wird.

Code: Alles auswählen

a = range(10)
b = a

del a

print b
Wenn nun dein Programm (der Python-Prozess) während der Laufzeit über 200 MB vom Betriebssystem anfordert, liegt es auch am Betriebssystem, diese wieder freizugeben. Oder das Betriebssystem entscheidet sich dafür, die 200 MB+ erstmal für den Prozess bereitzuhalten. Hierbei ist es unerheblich, ob dein Python-Programm diese auch wirklich benötigt. Einflussmöglichkeiten hast du da in der Regel keine.

Wie BlackVivi schon schrieb, kannst du das insoweit beeinflussen, als dass du dein Programm so gestaltest, dass der Python-Prozess möglichst wenig Speicher anfordern muss.

Grüße... Heiko
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Dienstag 13. Januar 2009, 14:23

hm, ok - ich habe es jetzt ersteinmal so gelöst, dass ich die Datenbank fülle und dann mein Programm neu starte.
Ich habe mir mit gc.get_objects() mal alle Objekte im Speicher ausgeben lassen, da ist wirklich noch alles drin - trotz del.
bwbgs Post dürfte dann auch den Grund dazu liefern :/

Mittelfristig werde ich wohl tatsächlich Häppchenweise arbeiten müssen.

Danke euch allen für die Hilfe!

Daniel
BlackJack

Dienstag 13. Januar 2009, 14:40

@Barabbas: Vergiss ``del``, bereinige am besten Dein Programm möglichst komplett davon. Nur um Namen zu löschen sollte man das eigentlich so gut wie nie verwenden.

Wenn die Objekte noch da sind, dann hältst Du irgend wo noch Referenzen auf die Objekte. Wo und warum? Wahrscheinlich nicht in Klassen, falls doch, wieder die Frage warum!? Eventuell in Modulen. Was ein Hinweis auf einen unschönen Entwurf ist.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Dienstag 13. Januar 2009, 15:21

@BlackJack: Ok, del ist draußen.
Ist schon alles in Klassen gegliedert, es gab allerdings dennoch modulare Variablen. Das habe ich bereinigt und meinen Entwurf zugleich auf "häppchenweise" umgestellt, jetzt läuft alles, wie es soll.
Auch wenn alle Variablen klassengebunden sind, gibt es das Speicherproblem.
Antworten