2009-07-17 9 views
1

Ich versuche dynamische Objekte zum erneuten Laden in Python zu implementieren, die Codeänderungen live widerspiegeln.Traversieren einer Python-Objektbaumstruktur

Das Neuladen von Modulen funktioniert, aber ich muss jede Instanz der Modulklassen neu erstellen, damit Änderungen wirksam werden.

Das Problem ist, dass Objekte Daten (Objekte Inhalt) während des Prozesses verloren geht.

So habe ich versucht, einen anderen Ansatz:

def refresh(obj, memo=None): 
    if memo is None: 
     memo = {} 
    d = id(obj) 
    if d in memo: 
     return 
    memo[d] = None 
    try: 
     obj.__class__ = getattr(sys.modules[obj.__class__.__module__], 
       obj.__class__.__name__) 
    except TypeError: 
     return 
    for item in obj.__dict__.itervalues(): 
     if isinstance(item, dict): 
      for k, v in item.iteritems(): 
       refresh(k, memo) 
       refresh(v, memo) 
     elif isinstance(item, (list, tuple)): 
      for v in item: 
       refresh(v, memo) 
     else: 
      refresh(item, memo) 

Und überraschenderweise funktioniert es! Nach dem Aufruf von refresh() für meine Objekte wird der neue Code wirksam, ohne dass sie neu erstellt werden müssen.

Aber ich bin mir nicht sicher, ob dies der richtige Weg ist, ein Objekt zu durchlaufen? Gibt es eine bessere Möglichkeit, die Komponenten eines Objekts zu durchlaufen?

Antwort

1

Siehe this recipe im Python Cookbook (oder vielleicht sogar besser seine Version in der "gedruckten", die ich glaube, dass Sie tatsächlich kostenlos mit Google Buchsuche lesen können, oder sicher auf O'Reillys "Safari" -Site mit ein kostenloses 1-wöchiges Probeabonnement - ich habe eine Menge an Hudsons Originalrezept bearbeitet, um die "gedruckte Buchversion" zu bekommen!

+0

Dies ist der von mir verwendeten Lösung sehr ähnlich (einige "Top Level" -Klassen sind umschlossen und verfolgen ihre Instanzen, um sie neu laden zu können). Das Problem besteht darin, dass ich nicht alle Klassen in mein Paket einbinden möchte (oder von einer wieder aufladenden Klasse wie in Ihrem Beispiel erben), sondern nur die obersten. Deshalb brauche ich eine Objektbaum-Traversierungsfunktion. –

+0

Ich glaube, Sie können es nicht mit vollständiger Allgemeinheit tun - abhängig von z.B. __slots__ und andere Metaklassen-Funktionalität, Python-Objekte können so codiert sein, dass sie das einfach nicht unterstützen (deshalb ist eine bestimmte Unterstützung erforderlich, wenn Sie Erweiterungen codieren, für Garbage-Collection-Traversals, schwache Referenzen, Picking/Unpickling, & C). Öffnen Sie Dateien, DB-Verbindungen, Generator-Objekte, Sperren, ... Wenn Sie riskieren, einige Teile zu verpassen, stellen Sie sicher, dass Sie mindestens Sätze, deques, default_factory Mitglieder von defaultdicts usw. usw. –

+0

Ok, dann habe ich einfach um weitere Typprüfungen in meinen Iterationen hinzuzufügen, wechseln Sie. Es wäre schön, irgendeine Art von has_sequence_interface/has_mapping_interface() -Funktionen zu haben, um zu testen, wie ein Objekt iteriert werden kann. –

0

Zum erneuten Laden von Python-Code habe ich diese Implementierung vor langer Zeit entwickelt.

http://www.codexon.com/posts/a-better-python-reload

Es ist wahrscheinlich der schnellste und sauberste Weg möglich.

+0

Ihr Code funktioniert nicht mit meinem (löst einen Fehler "AttributeError: __provides__" aus, ich denke, es spielt nicht gut mit zope.interface). Außerdem glaube ich nicht, dass es Instanzen in Instanzen neu laden kann, was ich versuche zu erreichen. –

+0

Es sollte nicht mit einem anderen Reloader interagiert werden. Was das erneute Laden von Instanzen innerhalb von Instanzen betrifft, so muss es dies nicht tun, da es die Klasse anstelle der Instanzen ändert. Angerufene Methoden werden automatisch in die neue Klasse übernommen. – Unknown

+0

Ich habe meinen gesamten Reload-Code deaktiviert, als Sie Ihren Code ausprobiert haben, indem Sie die reload() -Funktion auf Modulen ausgeführt haben, die neu geladen werden mussten. Entschuldigung, ich habe nicht verstanden, was es tut, ich werde versuchen, mein Problem zu debuggen, wenn ich Zeit habe. –