Seite 1 von 1
aus Submodul auf globale Variable in __main__ zugreifen
Verfasst: Mittwoch 25. Februar 2009, 16:26
von milki
Hallo,
Ich möchte ein Programm aufräumen und dabei einige Klassen in Module verschieben. Allerdings gibt es eine kleine Abhängigkeit zum Hauptprogramm.
Es gibt so ein gobales Konfigurations-obj, auf das einige der Klassen/Objekte(/Module) mitunter zugreifen müssen. Sieht ungefähr so aus:
Code: Alles auswählen
if (__name__ == "__main__"):
conf = Config() # liest .ini ein
#-- in Objekten/Modulen dann:
print conf.option1
print conf.play.option2
Als globales Objekt find ich das wesentlich nützlicher. Ansonsten müsste man ja die ganzen evtl. benötigten Optionen zusammensuchen und an alle anderen Objekte als __init__-Parameter übergeben -- oder das conf-Objekt selbst mehrfach herumreichen.
Wenn ich jetzt aber die Klassen in Module auslagere, hab ich von dort ja keinen Zugriff mehr auf die Variable "conf" im Hauptprogramm. Die Module haben alle ihren eigenen Namensraum, und mit "global" kommt man da ja offenbar nicht raus.
Natürlich könnte ich das conf-Modul einfach in den anderen Modulen laden, dort conf=Config() nochmal separat initialisieren. Allerdings hätt ich dann ein halbes Dutzend Kopien davon, und nur die Instanz im Hauptprogramm wäre wirklich aktuell. (Es gibt ein Konfigurationsmenü.)
Wie kann ich denn das eleganter lösen?
Gibt es sowas wie eine Referenz auf das Hauptprogramm? ("__main__" ist ja nur ein Beschreibungsname, aber selbst kein Objekt)
Hab mir überlegt das conf-Objekt vielleicht in die Module zu "injizieren":
Code: Alles auswählen
import module1
module1.conf = conf
import module2
module2.conf = conf
import module3
module3.conf = conf
Hmm, geht. Das ist scheinbar ein stabiler Workaround. Aber gibt es denn eine andere Standardlösung für solche Fälle?
Re: aus Submodul auf globale Variable in __main__ zugreifen
Verfasst: Mittwoch 25. Februar 2009, 16:41
von DasIch
Du kannst mit weakrefs eine Liste aller Instanzen des Konfiguration Objektes haben die du updatest sollte sich die Konfiguration verändern.
Verfasst: Mittwoch 25. Februar 2009, 17:05
von b.esser-wisser
Gibt es sowas wie eine Referenz auf das Hauptprogramm?("__main__" ist ja nur ein Beschreibungsname, aber selbst kein Objekt)
Warum sollte der Name "__main__" etwas extra-besonderes sein?
Wir sind hier doch bei Python, also probieren wir einfach das offensichtlichste aus

:
Code: Alles auswählen
#Datei test1.py
#! /usr/bin/env python
# coding:utf-8
TEST = ["Hallo", "Welt"]
import test2
test2.foo()
print test2.bar
Code: Alles auswählen
#Datei test2.py
import __main__ as main
from __main__ import TEST
bar = TEST[:]
def foo():
print dir(main)
Das funktioniert zumindest mal (Vorsicht bei "circular imports" d.h. wenn beide Module Objekte aus dem jeweils anderen brauchen,
während sie importiert werden).
hth, Jörg
Verfasst: Mittwoch 25. Februar 2009, 17:59
von helduel
Stelle in dem Config-Modul eine Funktion zur Verfügung, die dir immer dieselbe Instanz zurückgibt und rufe die immer auf, anstatt immer eine neu zu instanzieren.
Gruß,
Manuel
Verfasst: Mittwoch 25. Februar 2009, 21:21
von BlackJack
@milki: Lagere einfach nicht nur die Klassen in andere Module aus, sondern auch die Konfiguration in ein eigenes Modul. Das kannst Du dann überall importieren und hast immer Zugriff auf das selbe Config-Objekt.
Verfasst: Mittwoch 25. Februar 2009, 22:16
von milki
Wow. So viele Möglichekeiten.
Danke für eure Antworten!!
BlackJack: Ich hatte die Config-Klasse sogar schon in ein eigenes Modul gepackt. Und jetzt hab ich einfach mal die Idee mit der einen Instanz von helduel umgesetzt:
Code: Alles auswählen
# Modul config.py
def Config():
global conf_instance
try:
return conf_instance
except:
conf_instance = ConfigDict()
return conf_instance
Funktioniert.
Irgendwie hat es zwar nur mit try/except funktioniert -- Eine vordefinierte Variable in dem Modul wollte nicht so recht. Aber das muss ich nochmal in Ruhe ausprobieren...
Auf jeden Fall haben Module ihren eigenen Namensraum und der wird nur ein einziges mal initialisiert. Lustig.
b.esser-wisser:
Das Beispiel hab ich gleich mal ausprobiert. Funktioniert wie erhofft. Glücklicherweise hab ich in der Python-Doku aber schon gelesen daß man besser keine Module über Kreuz lädt - deswegen mach ich das auch nich..!!

hehe
Also in meinem Fall passt das eh nicht so gut, weil das Hauptprogramm doch noch relativ groß ist. Aber gut zu wissen, daß man es könnte!
Und __main__ existiert also doch irgendwo als richtiges Objekt.
http://mail.python.org/pipermail/python ... 37819.html
Re: aus Submodul auf globale Variable in __main__ zugreifen
Verfasst: Mittwoch 25. Februar 2009, 22:27
von milki
DasIch hat geschrieben:Du kannst mit weakrefs eine Liste aller Instanzen des Konfiguration Objektes haben die du updatest sollte sich die Konfiguration verändern.
Das hab ich mir auch mal angeguckt.
http://docs.python.org/library/weakref.html
Nur eine Instanz-Liste find ich hier vor lauter Funktionen nicht.
Aber für mein conf-Objekt wär das eh overkill. Ich glaub weakref könnt ich eher verwenden für ein paar große Listen/Dicts im Programm. Hab da so ne Art Zwischenspeicher, und dann müsst ich mich da nicht selbst ums Finden und Löschen alter Werte kümmern..
Verfasst: Mittwoch 25. Februar 2009, 23:12
von Kelhim
Könntest du nicht so was probieren?
config wäre dann in jedem Modul dasselbe, selbst wenn du noch Veränderungen an config vornehmen solltest, da Python beim Import immer prüft, ob das Modul nicht bereits vorher importiert wurde. Wenn der Import nicht in einer Klasse oder Funktion verpackt ist, gilt er global im jeweiligen Modul (also bei einem Import in jedem Modul überall). Bei vor Programmaufruf bestehenden Einstellungen, die sich ändern können, aber in jedem Modul berücksichtigt werden sollen, sehr nützlich.
Verfasst: Mittwoch 25. Februar 2009, 23:57
von BlackJack
@milki: Warum so kompliziert?
Verfasst: Donnerstag 26. Februar 2009, 00:21
von milki
Ja, das ist sogar der aktuelle Stand.
Ich hab da noch was im config-Modul vereinfacht. Statt dem Singletondingsi, hab ich da einfach gleich eine Instanz von der ursprüngichen Config-Klasse erzeugt:
Code: Alles auswählen
# config.py
class ConfigDict(object):
...
conf = ConfigDict()
Und jetzt binde ich das config-Modul im Hauptprogramm und in allen anderen Modulen einfach folgendermaßen ein:
Damit existiert im config-Modul einmalig eine Instanz des Objekts, und in allen Modulen, wo ich es brauche, hab ich eine Referenz darauf.
Scheint mir die sauberste Lösung zu sein.
Verfasst: Donnerstag 26. Februar 2009, 23:23
von DasIch
Ich hab mal ein Beispiel für eine Config mit weakref gemacht
http://paste.pocoo.org/show/105653/. In Config.__init__ würde man natürlich die Daten aus einer Datei oder so auslesen und in ConfigTransaction.commit da wieder speichern.