Seite 1 von 1

Problem mit __init__.py

Verfasst: Donnerstag 13. Januar 2022, 23:01
von pixewakb
Ich habe etwa folgende Ordner-Struktur:

main.py
settings.ini
/ Ordner: module
/ __init__.py
/ core.py
/ notify.py

In main steht drin:

Code: Alles auswählen

from module.core import main

if __name__ == "__main__":
    main()
In core fängt es dann mit

Code: Alles auswählen

from notify import send_email

...
Ich bekomme bei Start von main.py im Hauptverzeichnis folgende Fehlermeldung:

Code: Alles auswählen

ModuleNotFoundError: No module named 'notify'
Ich habe schon rausbekommen, dass Python die Module nicht findet. Dort wird dann vorgeschlagen, dass ich die __init__.py-Datei anpasse, was ich versucht habe, es funktioniert nur leider trotzdem nicht:

Code: Alles auswählen

from .notify import send_email
Ich habe dazu noch eine Frage: Mein Programm core.py soll die settings.ini geladen werden, also im Verzeichnis eine Etage da drüber. Klappt, solange ich core.py direkt starte und funktioniert wahrscheinlich nicht, wenn ich main.py starte. Da ich settings.py mit Direktpfad angebe und zwar "../settings.ini".

Kann mir jemand sagen, wie ich das Problem lösen kann.

Re: Problem mit __init__.py

Verfasst: Freitag 14. Januar 2022, 00:43
von __blackjack__
@pixewakb: Es wird nicht so ganz klar wo Du ``from .notify import send_email`` geschrieben hast. Das müsste dort stehen wo Du das importieren willst, also in `module.core`. In `module.__init__` würde das ja nichts nützen *dort* `send_email` als Name zur Verfügung zu haben. Ich persönlich gebe meistens den vollen Namen an, also ``from module.notify import send_email``.

"../settings.ini" ist keine gute Idee. Eben weil das vom aktuellen Arbeitsverzeichnis abhängt. Und das relativ zu einer Datei in dem Package zu machen, die dann aber ausserhalb des Packages liegt würde ich nicht machen. Was ist wenn man das Package dann mal regulär installieren möchte? Dann wäre die ``settings.ini`` an einem Ort an dem sie auf einigen Systemen von den Dateirechten her nicht mal liegen dürfte und sehr deplaziert. Relativ zur `main.py` ist's auch komisch, denn beim Installieren würde das ja auch irgendwo landen wo Programme liegen und keine anderen Dateien. Aber notfalls ginge es halt relativ zum `main`-Modul. Das müsste den Pfad dann beim Aufruf aus `__file__` ermitteln und übergeben.

Re: Problem mit __init__.py

Verfasst: Freitag 14. Januar 2022, 09:39
von rogerb
@pixewakb,

Der Ordner mit dem Namen "Module" ist eigentlich aufgrund der darin enthaltenen '__init__.py' ein Paket und kein Modul. Die darin enthaltenen .py Dateien sind die Module.

core.py und notify.py sind also Module im Paket 'module'.
Wenn du jetzt in core.py Namen aus notify.py importieren möchtest, geht das in core.py mit Punkt for dem notify so:

Code: Alles auswählen

from .notify import send_mail
Das kommt also *nicht* in die __init__.py sondern in core.py

main.py ist nicht Teil des Pakets. Main verwendet (importiert) das Paket oder Namen daraus.
Das kann man so machen wie du es versucht hast. Aber komfortabler wäre es in main.py einen solchen Import zu ermöglichen:

Code: Alles auswählen

from module import main
Dazu muss die __init__.py diese Zeile enthalten:

Code: Alles auswählen

from .core import main
Diese Vorgehensweise ist mein persönlicher Favorit, es gibt aber grundsätzlich mehrere Ansätze, so etwas aufzubauen.

Bzgl. der settings.ini kann ich __blackjack__ nur zustimmen. Alles was das Paket braucht gehört auch dort hinein. Allein schon für das Package-Management sollte alles kompakt gehalten werden.
Dass die Applikation dann später nach der Installation die settings.ini anderswo im Dateisystem ablegt ist natürlich auch möglich, hat aber nichts mit der Ausgangsstruktur des Pakets zu tun.