Ordnerstrukturierung

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
Hellstorm
User
Beiträge: 231
Registriert: Samstag 22. Juni 2013, 15:01

Hallo,

ich hab zwar im Internet gesucht, aber irgendwie steht dort so viel verschiedenes Zeug, dass ich einfach nicht durchblicke.

Also ich möchte mein Programm folgendermaßen aufteilen:

Im Wurzelverzeichnis soll halt nur eine Datei namens „start.py“ oder so liegen. Dann hätte ich gerne drei Ordner:

1. Das eigentliche Programm mit den ganzen Funktionen („src“)
2. Die PyQt-Formulare („gui“)
3. Übersetzungen („l18n“)

Ich weiß jetzt schon, dass ich in jedem Ordner eine __init__.py brauche, die beim import automatisch aufgerufen wird. Nur das funktioniert einfach nicht. Folgende Probleme:

Wenn ich in der start.py

Code: Alles auswählen

import src
schreibe, und in der src/__init__.py z.B.

Code: Alles auswählen

print("Hallo")
schreibe, dann funktioniert das. Aber diese __init__.py soll doch nur ein Ausgangspunkt sein, um die anderen Dateien aufzurufen, oder nicht? Aber wie rufe ich denn jetzt z.B. die Datei src/test.py auf? Ein „import test“ in der __init__.py funktioniert nicht. Ich habe auch gelesen, dass man vielleicht noch mal src schreiben soll: „import src.test“. Aber auch das funktioniert nicht. Ich bekomme dann z.B. einen „unhandled ImportError, No module named 'test'“.

Und wie würde ich überhaupt an die anderen Ordner herankommen, wenn ich mich schon im src-Ordner befinde?

Naja, wurde bestimmt schon gefragt und ausgiebig erklärt, und wahrscheinlich gibt es irgendwo eine total einfache Erklärung, die ich übersehen habe. Aber vielleicht könnte mir doch jemand helfen? :) Danke!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nun, die meisten `__init__.py` sind leer und dienen nur als Markierung fuer "dieser Ordner ist ein Paket". Auf die Module in einem Paket greift man dann so zu:

Code: Alles auswählen

import paket.modul
paket.modul.foo()

#oder
from paket import modul
modul.foo()
BlackJack

@Helstorm: Ein Package sollte einen vernünftigen Namen haben und nicht `src`. Du brauchst auch nicht in jedem Ordner eine `__init__.py` sondern nur in denen die auch tatsächlich ein Python-Package sein sollen, was bei 2. und 3. sicher nicht der Fall ist, denn die enthalten ja keinen Python-Quelltext, sondern Daten die vom Programm verwendet werden.

Ob und was in der `__init__.py` gemacht wird, hängt davon ab, ob Dein Package selbst Code enthalten soll. Oder ob es nur als Namensraum für die Module in dem Package dient.

Deine Wahl der Begriffe ist ein wenig eigenartig. `test.py` rufst Du nicht auf, das wäre eher etwas für eigenständige Programme, sondern Du importierst es. Und zwar normalerweise mit ``import src.test`` oder ``from src import test`` (oder direkt Namen aus dem Modul mit ``from src.test import spam`` (wenn es den Namen `spam` in dem Modul gibt)). Das funktioniert nur dann nicht, wenn das Package nicht in den Pfaden ist, den Python für Importe absucht. Da ist normalerweise neben den „globalen” Verzeichnissen, das aktuelle Arbeitsverzeichnis enthalten. Man muss das Programm also von der Konsole aus aus dem richtigen Verzeichnis starten, damit das klappt.
Hellstorm
User
Beiträge: 231
Registriert: Samstag 22. Juni 2013, 15:01

cofi hat geschrieben:Nun, die meisten `__init__.py` sind leer und dienen nur als Markierung fuer "dieser Ordner ist ein Paket". Auf die Module in einem Paket greift man dann so zu:
Jetzt verstehe ich das. Danke :) Ich habe mir den Quelltext von Anki angeschaut, und da stand in den __init__.pys immer etwas drin. Deswegen war ich etwas verwirrt.
BlackJack hat geschrieben:@Helstorm: Ein Package sollte einen vernünftigen Namen haben und nicht `src`. Du brauchst auch nicht in jedem Ordner eine `__init__.py` sondern nur in denen die auch tatsächlich ein Python-Package sein sollen, was bei 2. und 3. sicher nicht der Fall ist, denn die enthalten ja keinen Python-Quelltext, sondern Daten die vom Programm verwendet werden.
Ok, dann war das ein Verständnisfehler meinerseits. Danke. Zu „src“... naja, da war ich mir jetzt noch nicht sicher, wie ich das nennen sollte. Ich würde da halt gerne das eigentliche Programm hineinspeichern, damit ich im Wurzelverzeichnis kein so großes Chaos habe, sondern nur ein oder zwei Dateien. Was wäre denn ein guter Titel dafür?

Mein Programm soll Dateien auf einen FTP-Server laden und nach einer bestimmten Zeit wieder löschen (Habe das hier schon einmal angesprochen). Im Moment heißt das Programm in einem Anfall von grenzenloser Kreativität „Uploader“.

BlackJack hat geschrieben: Deine Wahl der Begriffe ist ein wenig eigenartig. `test.py` rufst Du nicht auf, das wäre eher etwas für eigenständige Programme, sondern Du importierst es. Und zwar normalerweise mit ``import src.test`` oder ``from src import test`` (oder direkt Namen aus dem Modul mit ``from src.test import spam`` (wenn es den Namen `spam` in dem Modul gibt)). Das funktioniert nur dann nicht, wenn das Package nicht in den Pfaden ist, den Python für Importe absucht. Da ist normalerweise neben den „globalen” Verzeichnissen, das aktuelle Arbeitsverzeichnis enthalten. Man muss das Programm also von der Konsole aus aus dem richtigen Verzeichnis starten, damit das klappt.
Ahh, ok. Ich habe das Programm einfach in Eric mit „Skript ausführen“ gestartet. Wahrscheinlich war dann der Wurzelordner des Programms nicht im Pfad.

Und ich werde ab jetzt die richtigen Begriffe verwenden :)

Danke an euch beide!
BlackJack

@Helstorm: Wie gesagt, in die `__init__.py` kommt der Code der im „Package-Modul” stehen soll. Das muss nicht leer sein, aber wenn Dein Package bisher nicht einmal einen vernünftigen Namen hatte, wüsste ich so auf Anhieb nicht was dort rein gehört.

Beim obersten Package würde ich in der `__init__` Metainformationen hinterlegen, wie einen Docstring, der das ganze Package beschreibt, und Attribute wie `__author__` und `__version__`. Man kann dort mit `__all__` auch alle öffentlichen Module und Subpackages aufführen wenn man möchte.
Antworten