Anfängerfrage: Import eigener *.py

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
Benutzeravatar
CoderGirl
User
Beiträge: 74
Registriert: Samstag 22. April 2017, 17:47

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
Nur ein Mädchen, das nie so viel weiss, wie die Jungs :ugeek:
Alfons Mittelmeyer
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.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@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.
Benutzeravatar
CoderGirl
User
Beiträge: 74
Registriert: Samstag 22. April 2017, 17:47

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
Nur ein Mädchen, das nie so viel weiss, wie die Jungs :ugeek:
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

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?
Alfons Mittelmeyer
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:

Code: Alles auswählen

class Access():

    def __init__(self):
        self.var1 = "Test 1"  # base.var1

    def output(self): # base.output
        print(self.var1)
Im Main Script kann man das nachladen und darauf zugreifen:

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()
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@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

Code: Alles auswählen

base = reload(base)
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.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@CoderGirl: das von Sirius3 gezeigte

Code: Alles auswählen

reload(base)
funktioniert in Python2. In Python3 ist diese Funktion entfallen, kann aber weiterhin importiert werden:

Code: Alles auswählen

import imp
imp.reload(base)
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.
Benutzeravatar
CoderGirl
User
Beiträge: 74
Registriert: Samstag 22. April 2017, 17:47

Hallo

herzlichen Dank.

Ich probiere das umgehend mal aus.

Danke euch

codergirl
Nur ein Mädchen, das nie so viel weiss, wie die Jungs :ugeek:
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

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.
Wenn imp.reload klappt, ist das die Beste Lösung.

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.
Benutzeravatar
CoderGirl
User
Beiträge: 74
Registriert: Samstag 22. April 2017, 17:47

Hallo zusammen,

ich halte euch auf dem laufenden.
Hocke mich eh die Woche nochmal dran :)

lg
codergirl
Nur ein Mädchen, das nie so viel weiss, wie die Jungs :ugeek:
Antworten