Verehrte Gurus, weiß jemand von euch, was passiert, wenn ich Module über __import__ importiere und anschließend die noch einmal importiere? Werden diese Module dann noch einmal von der Platte gelesen (also, wird hier unnötig CPU-Zeit verbraten)? Oder merkt der Interpreter, daß das Modul schon geladen wurde und läßt es dann gut sein? Hintergrund meiner Frage ist, daß ich in Abhängigkeit einer Konfigurationsdatei Module schon einmal laden will und dann später mit einer class factory die darin enthaltenen Klassen instantiieren will. Eigentlich würde ich sie noch lieber zuvor generisch instantiieren und dann nur noch eine Standardmethode aufrufen, aber ich weiß noch nicht, wie ich eine Instanz anspreche, von der ich nur den Namen in einem dictionary, also in Form eines Strings habe. Danke schon mal für die Tipps! Markus _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
--On 2. Juli 2006 22:13:39 +0200 Markus Heller <markus@relix.de> wrote:
Verehrte Gurus,
weiß jemand von euch, was passiert, wenn ich Module über __import__ importiere und anschließend die noch einmal importiere?
Werden diese Module dann noch einmal von der Platte gelesen (also, wird hier unnötig CPU-Zeit verbraten)? Oder merkt der Interpreter, daß das Modul schon geladen wurde und läßt es dann gut sein?
i.A. gilt: importiert ist importiert. Ein bereits importiertes Modul wird nicht neugeladen - außer Du verwendest explizit reload() oder wenn Du das Modul auf dem modules Dict explizit löschst. -aj _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Markus Heller wrote:
Werden diese Module dann noch einmal von der Platte gelesen (also, wird hier unnötig CPU-Zeit verbraten)? Oder merkt der Interpreter, daß das Modul schon geladen wurde und läßt es dann gut sein?
Nein, nur beim ersten mal. Danach ist das Modul in sys.modules gespeichert und wird beim nächsten import da gefunden.
Eigentlich würde ich sie noch lieber zuvor generisch instantiieren und dann nur noch eine Standardmethode aufrufen, aber ich weiß noch nicht, wie ich eine Instanz anspreche, von der ich nur den Namen in einem dictionary, also in Form eines Strings habe.
objekt = dictionary["name"] Ciao, Martin _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Hi Am 03.07.2006 09:27:39 schrieb Martin v. Löwis:
Nein, nur beim ersten mal. Danach ist das Modul in sys.modules gespeichert und wird beim nächsten import da gefunden.
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden. Hintergrund ist, dass ich pyVideo mit pygame und wxPython nutzen will. Da ist die grobe Reihenfolge in etwa: 1. wxPanel erzeugen, wo das pygame-surface dargestellt werden soll 2. pygame importieren 3. pyVideo importieren pyVideo muß nach pygame importiert werden, damit das SDL-Surface verwendet wird. pygame darf aber erst importiert werden, wenn das wxPanel steht. Gleichzeitig möchte ich aber pyVideo am Anfang importieren, damit der Nutzer die richtige Kamera auswählen kann. Das heisst ich muss dann pyVideo reimportieren... Alternativ könnte ich versuchen, das Fenster-Handle für pygame umzubiegen... aber da weiss ich im Moment nicht mal ob das überhaupt geht. cu boesi _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
--On 3. Juli 2006 11:46:23 +0200 Alexander 'boesi' Bösecke <boesi.josi@gmx.net> wrote:
Hi
Am 03.07.2006 09:27:39 schrieb Martin v. Löwis:
Nein, nur beim ersten mal. Danach ist das Modul in sys.modules gespeichert und wird beim nächsten import da gefunden.
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden.
reload() -aj _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden.
Theoretisch: reload.
Hintergrund ist, dass ich pyVideo mit pygame und wxPython nutzen will. Da ist die grobe Reihenfolge in etwa:
1. wxPanel erzeugen, wo das pygame-surface dargestellt werden soll 2. pygame importieren 3. pyVideo importieren
pyVideo muß nach pygame importiert werden, damit das SDL-Surface verwendet wird. pygame darf aber erst importiert werden, wenn das wxPanel steht. Gleichzeitig möchte ich aber pyVideo am Anfang importieren, damit der Nutzer die richtige Kamera auswählen kann. Das heisst ich muss dann pyVideo reimportieren...
Du kannst es wie oben gesagt mit reload versuchen. Aber da es sich dabei um C-Extensions handelt, weiss ich nicht ob das von praktisch von Erfolg gekrönt ist. Diez _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Hallo, On 2006-07-03 15:11, Diez B. Roggisch wrote:
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden.
Theoretisch: reload.
das "theoretisch" unterschreibe ich sofort. ;-) Bei reload ist knifflig, dass bspw. bereits instanziierte Objekte nicht "automagisch" ihre Klasse ändern, wenn ein Modul mit der Klasse darin neu geladen wird. Beispiel: $ cat test.py class C(object): pass $ python Python 2.4.3 (#1, Jun 29 2006, 16:00:56) [GCC 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
import test c1 = test.C() isinstance(c1, test.C) True reload(test) <module 'test' from 'test.pyc'> c2 = test.C() c1.__class__ is c2.__class__ False isinstance(c2, test.C) True isinstance(c1, test.C) False
Für andere Objekte im Namensraum des neu geladenen Moduls gilt Entsprechendes; gibt es noch alte Referenzen aus der Zeit vor dem Reload, verweisen diese weiterhin auf das ursprüngliche Objekt. $ cat test.py config = True $ python Python 2.4.3 (#1, Jun 29 2006, 16:00:56) [GCC 3.3.6 (Gentoo 3.3.6, ssp-3.3.6-1.0, pie-8.7.8)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
import test c = test.config c True # setzen von config = False in test.py ... reload(test) <module 'test' from 'test.py'> test.config False c True
Ich will gar nicht darauf hinaus, dass reload "intelligenter" sein sollte; das würde vermutlich nur in Krampf ausarten. Die Konsequenz ist vielmehr, dass ich reload bis auf gelegentliche Verwendung im interaktiven Interpreter vermeide. Ich nehme an, dass sich in den allermeisten Fällen, bei denen sich vermeintlich reload anbietet, eine andere Lösung finden lässt. Viele Grüße Stefan _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Alexander 'boesi' Bösecke wrote:
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden.
Dazu kannst Du reload() verwenden.
Hintergrund ist, dass ich pyVideo mit pygame und wxPython nutzen will. Da ist die grobe Reihenfolge in etwa:
1. wxPanel erzeugen, wo das pygame-surface dargestellt werden soll 2. pygame importieren 3. pyVideo importieren
pyVideo muß nach pygame importiert werden, damit das SDL-Surface verwendet wird.
Das erscheint mir falsch; es sollte einen anderen Weg geben, pyVideo zu konfigurieren (also nicht durch import, sondern nachträglich). Ciao, Martin _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Hi Am 03.07.2006 16:11:45 schrieb Martin v. Löwis:
Alexander 'boesi' Bösecke wrote:
Ok und wie erreicht man das genaue Gegenteil? Bei einem Reimport soll also das Modul erneut initialisiert werden, so als wäre es noch nicht importiert worden.
Dazu kannst Du reload() verwenden.
Tja wie schon einige andere geschrieben haben, ist reload leider nicht immer die richtige Wahl. Konkret in meinem Fall bedeutet das, dass die von pyVideo importierten Module CRImage und/oder RImageSDLc nicht ebenfalls reimportiert werden. Ich hab das jetzt folgendermaßen gelöst: fp, pathname, description = imp.find_module('WebCap') wc = imp.load_module('WebCap', fp, pathname, description) Laut Doku soll zwar load_module das selbe wie reload tun, aber der obige Code funktioniert im Gegensatz zu reload. Es gibt nur ein Problem, wenn ich das mit pyexe kompiliere, wird beim Ausführen gemeckert, dass WebCap nicht gefunden wird.
Das erscheint mir falsch; es sollte einen anderen Weg geben, pyVideo zu konfigurieren (also nicht durch import, sondern nachträglich).
Da stimme ich dir auf jeden Fall zu, aber zumindest ist so eine Konfigurationsmöglichkeit nicht dokumentiert. Ich werde mich mit dem allen noch intensiver beschäftigen. Meine Mail hier war eher eine spontane Reaktion auf das Thema, in der Hoffnung dass es eine einfache Lösung gibt, die über reload hinausgeht. cu boesi _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Hi Oh man mit import und reload kann man sich ja so richtig ins Knie schiessen. Ich beschreib jetzt einfach mal einfach meine Erfahrungen und Experimente. Wenn ich Müll verzapfen sollte, korrigiert mich bitte.
Ich hab das jetzt folgendermaßen gelöst: fp, pathname, description = imp.find_module('WebCap') wc = imp.load_module('WebCap', fp, pathname, description) Laut Doku soll zwar load_module das selbe wie reload tun, aber der obige Code funktioniert im Gegensatz zu reload.
Das ist natürlich vollkommener Humbug und funktioniert nur, weil ich WebCap über 2 Wege importieren kann 1. import pyVideo.WebCap - pyVideo ist ein package 2. import WebCap - in meinem site-packages Verzeichnis ist eine pth-Datei mit dem Inhalt "pyVideo" Scheinbar erkennt Python nicht, das es sich hier 2x um das gleiche Modul handelt. Im Zusammenhang mit reload stellen sich mir jetzt noch ein paar Fragen. Wenn Modul1 das Modul2 importiert, wie reloadet man Modul2, wenn Modul1 reloadet wird? Mir fällt dazu nur ein, vor dem Import von Modul2 nachzusehen ob Modul2 in locals enthalten und dann reload zu verwenden. Das funktioniert aber nicht mehr, wenn Modul2 mit "from Modul2 import *" importiert wird. In diesem Fall stellt sich aber generell die Frage, wie Modul2 reloadet wird. Zwischendurch hatte ich das gelöst, in dem ich im Modul WebCap vor dem "from CRImage import *" folgendes gesetzt hab: if 'RImageSDLInstalled' in locals(): import CRImage reload(CRImage) Das funktioniert soweit zwar, aber sieht doch ganz schön nach Hack aus und ist irgendwie gar nicht mehr "python-like"... Da es ja letzten Endes um den reload von CRImage geht, hab ich das so gelöst: import WebCap as wc ... import CRImage reload(CRImage) reload(wc) Funktioniert seltsamerweise aber nur, wenn ich WebCap und nicht pyVideo.WebCap importiere. pyVideo.WebCap sieht das reloadete CRImage nicht. Eine letzte Frage noch: Im Modul CRImage wird das C-Modul RImageSDLc importiert, das wird beim reload von CRImage automatisch reloadet - ist das bei C-Modulen generell so oder nur in diesem speziellen Fall? cu boesi PS: Ich weiss, dass reload im Deutschen nicht existiert, aber da "donwload" ein deutsches Verb ist, hab ich mir mal die Freiheit genommen reload einzudeutschen... _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Hallo Alexander, On 2006-07-13 12:53, Alexander 'boesi' Bösecke wrote:
Oh man mit import und reload kann man sich ja so richtig ins Knie schiessen. Ich beschreib jetzt einfach mal einfach meine Erfahrungen und Experimente. Wenn ich Müll verzapfen sollte, korrigiert mich bitte.
Ich hab das jetzt folgendermaßen gelöst: fp, pathname, description = imp.find_module('WebCap') wc = imp.load_module('WebCap', fp, pathname, description) Laut Doku soll zwar load_module das selbe wie reload tun, aber der obige Code funktioniert im Gegensatz zu reload. [...]
zu diversen reload-Problemen habe ich ja schon woanders in diesem Thread geschrieben. In einem Projekt haben wir, als wir feststellten, dass wir eine Reinitialisierung eines Moduls brauchen, eine reload-Funktion im Modul hinzugefügt. Diese machte gut genug, was wir wollten. _Warum_ musst du eigentlich das Modul oder gar mehrere neu laden? Kannst du die Sachen, die das Modul beim Import erledigt und die du re-initialisieren willst, nicht bei einem bereits geladenen Modul ausführen (bzw. die Sachen, die für dich nötig sind)? Wenn du nicht vielem Client-Code Tricksereien aufbürden willst, könnte es sich lohnen, ein eigenes Modul als Schnittstelle zu verwenden.
PS: Ich weiss, dass reload im Deutschen nicht existiert, aber da "donwload" ein deutsches Verb ist, hab ich mir mal die Freiheit genommen reload einzudeutschen...
Im Deutschen verwende ich Download nur als Hauptwort, statt "downloaden" sage ich "herunterladen". "Downloaden" und "reloaden" klingen in meinen Ohren furchtbar. Statt "reloaden" geht "neu laden" oder "nachladen" (fast) genau so gut; es kann höchstens sein, dass reload von mehr Leuten verstanden wird, weil die Python-Funktion so heißt. Normalerweise ist aber aus dem Betreff oder dem ersten Satz erkennbar, wenn es um reload- Probleme geht. ;-) Viele Grüße Stefan _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
participants (6)
-
"Martin v. Löwis"
-
Alexander 'boesi' Bösecke
-
Andreas Jung
-
Diez B. Roggisch
-
Markus Heller
-
Stefan Schwarzer