Hallo,
ich habe eine eigene base.py geschrieben, die ich auch erfolgreich in meine main.py
importiere und benutzen kann.
Nur habe ich das Problem, dass ich beim Ändern dern base.py die Änderungen nicht
nutzen kann, da die Funktionen nicht verfügbar sind.
Speicher ich unter neuem Namen ab und imprtiere diese "neue" base.py dann
klappt es und es sind auch die Änderungen da.
Irgendetwas muss ich sicher als Zwischenschritt machen, aber bin da ein wenig ratlos :K
Danke
lg
codergirl
Anfängerfrage: Import eigener *.py
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Also bei mir funktioniert es. Änderst Du vielleicht diese base.py während Python noch läuft? Mehrfachimport geht nicht.
Ansonsten müßte man das näher untersuchen. Im Subverzeichnis __pycache__ gibt es dann eine Datei, die etwa heißen könnte: base.cpython-34.pyc, jedenfalls mit base anfängt.
Lösche die einfach mal raus.
Normalerweise sollte python mitbekommen, dass ein Änderung gemacht wurde und neu übersetzen anstatt das bereits compilierte Modul zu nehmen. Warum es das bei Dir nicht mitbekommt, weiss ich nicht.
Ansonsten müßte man das näher untersuchen. Im Subverzeichnis __pycache__ gibt es dann eine Datei, die etwa heißen könnte: base.cpython-34.pyc, jedenfalls mit base anfängt.
Lösche die einfach mal raus.
Normalerweise sollte python mitbekommen, dass ein Änderung gemacht wurde und neu übersetzen anstatt das bereits compilierte Modul zu nehmen. Warum es das bei Dir nicht mitbekommt, weiss ich nicht.
@codergirl: Führst Du den Import vom interaktiven Terminal aus? Ein reimport ist seit Python3 nicht mehr vorgesehen. Wenn Du von der Kommandozeile aus mit 'python main.py' das Modul 'main.py' ausführst, sollte der import einwandfrei funktionieren.
Hallo,
einen wunderschönen guten Morgen!
Ich nutze Python über den Scripteditor eines GIS-Systems.
Mglw. liegt es an dem genannten Re-Import, der dann nicht mehr klappt.
Naja, dann ändere ich sie halt sukzessive ab und lade sie jeweils über einen
neuen Namen ein: Ist jetzt auch kein Riesenaufwand!
Ging mir nur drum, warum ich es mir nicht erklären konnte, warum
Vielen Dank
lg
codergirl
einen wunderschönen guten Morgen!
Ich nutze Python über den Scripteditor eines GIS-Systems.
Mglw. liegt es an dem genannten Re-Import, der dann nicht mehr klappt.
Naja, dann ändere ich sie halt sukzessive ab und lade sie jeweils über einen
neuen Namen ein: Ist jetzt auch kein Riesenaufwand!
Ging mir nur drum, warum ich es mir nicht erklären konnte, warum
Vielen Dank
lg
codergirl
Nur ein Mädchen, das nie so viel weiss, wie die Jungs
Klingt nicht nach einer brauchbaren Lösung. Auf mittlere Sicht - falls Du gerade mit Python startest - wirst Du mehr und mehr Bibliotheken nutzen müssen, d. h. das wird dann irgendwann nicht mehr gangbar sein. Kann das ein Problem des GIS-Systems sein? Hast Du mal andere Anwender (Kolleginnen und Kollegen) gefragt, wie sie das Problem lösen?
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
@CoderGirl: Wenn das Gis System ein Python Programm ist und nicht nach Ändern des Moduls Heruntergefahren und wieder gestartet werden soll, dann gibt ves auch noch eine andere Lösung.
Mit dieser habe ich sehr gute Erfahrungen gemacht. Sie ist aber in diesem Forum verpönt. Man importiert kein Modul sondern lädt ein Script nach.
Das Script muss dann auch etwas anders aussehen, als ein Modul. Alles was im Modul war, muss dann in eine Klasse eingerückt werden, etwa:
Im Main Script kann man das nachladen und darauf zugreifen:
Mit dieser habe ich sehr gute Erfahrungen gemacht. Sie ist aber in diesem Forum verpönt. Man importiert kein Modul sondern lädt ein Script nach.
Das Script muss dann auch etwas anders aussehen, als ein Modul. Alles was im Modul war, muss dann in eine Klasse eingerückt werden, etwa:
Code: Alles auswählen
class Access():
def __init__(self):
self.var1 = "Test 1" # base.var1
def output(self): # base.output
print(self.var1)
Code: Alles auswählen
def dyn_access(filename):
exec(compile(open(filename, "r").read(), filename, 'exec'))
return locals()['Access']()
base = dyn_access('base.py')
base.output()
base.var1 = "Test 2"
base.output()
@Alfons Mittelmeyer: jetzt solltest Du noch verraten, was der Unterschied zwischen einem Skript und einem Modul ist. Ob es Klassen gibt oder nicht, spielt dabei nämlich keine Rolle.
Und auch Dein kompliziertes Konstrukt verhindert nicht, dass Module nur einmal geladen werden und bei Veränderung nicht nocheinmal.
Das einfachere
macht das selbe, ohne irgendwelche unsinnigen Klassen einführen zu müssen. Das Problem bleibt, das ArcGIS eine Pythonumgebung in seiner Shell hat und es deswegen zu Seiteneffekten kommt.
Und auch Dein kompliziertes Konstrukt verhindert nicht, dass Module nur einmal geladen werden und bei Veränderung nicht nocheinmal.
Das einfachere
Code: Alles auswählen
base = reload(base)
@CoderGirl: das von Sirius3 gezeigte
funktioniert in Python2. In Python3 ist diese Funktion entfallen, kann aber weiterhin importiert werden:
Zwischenzeitlich aus base.py entfernte Objekte können im importierten Namespace dabei aber erhalten bleiben. Ob das für Deine GIS Umgebung hilfreich ist, kann ich leider nicht beantworten.
Code: Alles auswählen
reload(base)
Code: Alles auswählen
import imp
imp.reload(base)
-
- User
- Beiträge: 1715
- Registriert: Freitag 31. Juli 2015, 13:34
Wenn imp.reload klappt, ist das die Beste Lösung.Sirius3 hat geschrieben:@Alfons Mittelmeyer: jetzt solltest Du noch verraten, was der Unterschied zwischen einem Skript und einem Modul ist. Ob es Klassen gibt oder nicht, spielt dabei nämlich keine Rolle.
Und auch Dein kompliziertes Konstrukt verhindert nicht, dass Module nur einmal geladen werden und bei Veränderung nicht nocheinmal.
Was der Unterschied zwischen Scriptund Modul ist?
Der Code des Moduls wird beim ersten import ausgeführt und außerdem wird daraus etwas fest in den Speicher geladen, das wie ein Objekt - also wie eine instanzierte Klasse mit Punkt Operator ansprechbar ist.
Weiter imports führen dann den Code nicht mehr aus, sondern liefern nur eine Referenz auf dieses Modulobjekt also immer nur gewissermaßen auf dieselbe Instanz. Dadurch können auch Zustände global über das Modul übergeben werden.
Mit read und exec dagegen wird das Script immer ausgeführt, und wenn es sich geändert hat, dann wird das geänderte Script ausgeführt. Werden Namen in diesem Script definiert, so sind sie nur lokal für die aufrufende Funktion - hier dyn_access - verfügbar. Der Zugriff muss aber dann mit locals()['name'] erfolgen.
Damit etwas vom Script nach Ausführung übrigbleibt, instanziert meine Funktion ein Objekt der Klasse Access des Scripts und gibt die Referenz darauf zurück. Dieses Objekt ist nicht global vorhanden, sondern wird lediglich an eine Variable (hier base) gebunden.
Wenn andere Module auch auf dieselbe Instanz zugreifen möchten, müße man ihnen diese Referenz namens base übergeben. Wenn andere Module selber auch diese Funktion dyn_access aufrufen würden, erhielten sie eine eigene Instanz. Datenaustausch mit anderen Modulen oder globale Zustände über so ein Script müßte in diesem Fall über ein weiteres Modul erfolgen, das vom Script importiert wird.
Also, wenn imp.reload funktioniert, dann jedenfalls imp.reload nehmen.
Meine Scripts mittels dyn_access sind eigentlich nicht als Modulersatz gedacht, sondern für manchmal zusätzlich benötigte Aufgaben, bei denen nach Ausführung die dafür verwendeten Objekte wieder beseitigt werden. Es geht dabei also um etwas, das man nur lokal und temporär gelegentlich braucht. Eine modulähnliche Verwendung wäre machbar, aber sollte man wegen dem zusätzlichen Aufwand nicht tun, wenn es auch auf die für Module normale Weise geht.
Hoppla, man könnte natürlich dieses dyn_access auch in ein Modul legen und mit einer weiteren Funktion dafür sorgen, dass andere Module dann eine Referenz bekommen, wenn schon eine Instanz existiert. Also kann man es doch wie ein Modul machen. Lediglich bleibt dann der Aufwand, dass man dann aus einem Modulinhalt händisch eine Klasse machen muss, während ein import das schon selber erledigt.