Python-Module in Ordnern Organisieren

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
Krie9er
User
Beiträge: 22
Registriert: Montag 30. März 2020, 20:06

Hallo liebe Community,

ich sitze gerade an meinem PYTHON Programm und erstelle die Logik, die ich in der Ordnerstruktur haben möchte.

Im Kern habe ich 2 Fragen:

1. Wie kann ich über mehrere Ordner hinweg Pakete importieren?
2. Wie kann ich die Übersetzungen kapseln, sodass ich am liebsten für jedes Fenster eine Sprachdatei je Sprache habe.

Ich habe nun folgende Struktur:
  • \bin #das Hauptpaket in dem alles liegen soll
  • \bin\assets # für alle Assets, die die Application nutzt
    [*]\bin\controllers #für alle funktionen, die auf die einzelnen Views bezogen sind
  • \bin\languages #Sprachen
  • \bin\views #qt windows
  • \config #user-config der Installation
  • \gui #Qt Projektordner
  • programm.py # das eigentliche Programm
  • build.py # der Builder, der die Qtviews erzeugt in in den bin\views ordner ablegt.
Die Namenskonvention soll sein:
Views:
FensterNameAusQt.py mit gleichnamiger Klasse

Controllers:
fensterNameAusQtController.py mit gleichnamiger Klasse


Ferner möchte ich für die Sprachen eigentlich auch die Sprachdateien am liebsten auf jede View runterkapseln, jedoch habe ich noch keinen Weg gefunden wie ich das realisieren kann/bzw auch keine Idee dazu nutzen wollte ich hierfür getText
Mein Wunsch wäre:
languages\de\FensterNameAusQt.mo
languages\en\FensterNameAusQt.mo
usw.

Der gui-Ordner und die build.py werden am Ende nicht mit ausgeliefert.

Ich freue mich auf euer Feedback, was haltet ihr von dieser Struktur?

Freundliche Grüße und schöne Ostertage!
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krie9er: Eine Klasse pro Modul macht Module als Organisationsmittel überflüssig. Du programmierst in Python und nicht in Java.

Das mit der ``build.py`` klingt nach generiertem Code statt die *.ui-Dateien zur Laufzeit zu laden. ``build.py`` und `\bin\views\` fallen dann schon mal weg. Dafür wird der gui-Ordner mit ausgeliefert wenn da die *.ui-Dateien liegen.

"bin" ist ein komischer Name. In so einem Verzeichnis erwartet man kompilierte Binärdateien. Und nur die. Keine Unterverzeichnisse.

Wenn das ein Python-Paket sein soll, dann würde da der Paketname hingehören.

Bei einem Qt-Programm würde ich auch start überlegen ob ich nicht die Qt-Funktionalität für Mehrsprachigkeit verwende.

Das Aufteilen von Sprachdateien nach Fenstern ist keine gute Idee. Macht unnötig arbeit und ist eine Fehlerquelle weil es inkonsistente Übersetzungen fördert.

Die erste Frage ist mir nicht so ganz klar. Packages müssen in einem Pfad liegen wo sie von Python gefunden werden. Das aktuelle Arbeitsverzeichnis beim Start des Programms ist da üblicherweise dabei. Man muss also dafür sorgen, dass das beim Start passt. Ansonsten ist die saubere Lösung, Packages zu installieren. Für ein Startskript, das im Verzeichnis liegt wo die Packages sind, könnte man noch das Verzeichnis in dem dieses Skript liegt vorne in die Suchpfade einfügen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Krie9er
User
Beiträge: 22
Registriert: Montag 30. März 2020, 20:06

Danke @blackjack für diese ausführliche Antwort!

Zur Mehrsprachigkeit habe ich mir mit einem Tutorial nun geholfen :-) somit ist mir das nun klar.

Ich werde den bin Ordner in den Programmnamen ändern, danke für die Erklärung an dieser Stelle!

Bzgl. den Views sowohl meine Tutorials als auch in meinem Kurs wurde immer mit einer Build gearbeitet. Kann ich denn einfach die UI von qt direkt laden?

Bisher habe ich immer das Frontend nach jeder Änderung neu in .py umgewandelt:

Code: Alles auswählen

from qtpy import uic

uic.compileUiDir("gui")
wie könnte ich das anders machen?

Ehrlich gesagt clustere ich sehr gern meine Klassen/Strukturen, da ich eigentlich nicht so gern mit Dateien arbeite die mehr als 1000 Zeilen haben.
Der Ordnung wegen wollte ich deshalb auch die Logik, also was getan werden soll in den Unterordner {appname}\controllers legen. Dort gäbe es dann für jedes Fenster einen Controller, der die Interaktionen händelt und einen Bereich der die eigentlichen Berechnungen etc durchführt.

Wenn das keine gute Idee ist, so ändere ich gerne mein Pattern, ich möchte nur nicht viel code in einer Datei haben bzw. viele Dateien die unterschiedliche Funktionen haben in einem selben Ordner.

Danke!
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krie9er: Die einzige Funktion die das `qtpy.uic`-Modul garantiert bietet ist `loadUi()`. Alles andere nur wenn man PyQt verwendet. Und diese Funktion ist die, mit der man *.ui-Dateien zur Laufzeit lädt.

Gibt es einen Grund warum Du `qtpy` dazwischen schaltest und nicht direkt eine der Qt-Anbindungen verwendest? Wie man beim `qtpy.uic`-Modul sehen kann gibt es trotzdem Unterschiede auf die man achten muss, und man muss dann eigentlich auch die Anwendung mit allen drei Backends ausgiebig testen um sicher zu sein, dass es auch tatsächlich funktioniert.

Ich finde 1000 Zeilen auch eine grenze ab der es Zeit wird über die Aufteilung von Modulen nachzudenken, aber bei Dir sieht das so aus als wenn jede Klasse diese Ausmasse erreicht. Das erscheint mir recht unwahrscheinlich zu sein.

Das Du keine Dateien mit unterschiedlichen Funktionen im selben Ordner haben möchtest, klingt genau wie eine Klasse pro Modul danach, dass Du das Modul als Organisationseinheit überspringen möchtest. Man hat normalerweise ein Package für die Anwendung. Darin dann den Code thematisch sinnvoll auf Module verteilt. Wenn ein Modul zu gross wird, kann man es problemlos durch ein Package ersetzen in dem das Modul auf mehr als ein Modul unterteilt ist.

Mal als Beispiel mal hat ein Programm das als Modul anfängt und Funktionen und Klassen zum Lesen, Verarbeiten, und Schreiben von Daten enthält und eine `main()`-Funktion:

Code: Alles auswählen

program.py
Und das wird jetzt zu gross. Also möchte man den Inhalt thematisch aufteilen, beispielsweise genau an den drei genannten Gruppen:

Code: Alles auswählen

program/
    __init__.py
    input.py
    processing.py
    ouput.py
    gui.py
start_program.py
`__init__` enthält dann gemeinsamen Code, beispielsweise Konstanten und die `main()`-Funktion aus dem ursprünglichen `program.py`. Die anderen Module entsprechend die thematischen Funktionen und Klassen.

Und falls dann irgendein Modul wieder zu gross werden sollte, kann man das wieder durch ein Package mit dem Modulnamen ersetzen. In der dort neuen `__init__.py` kann man dann auch die ursprünglichen öffentlichen Funktionen und Klassen importieren, so dass sich durch das Aufteilen des Moduls aus Sicht der anderen Module nichts ändert.

Bei so einer Aufteilung können natürlich auch Module mit nur einer Klasse entstehen, da muss man dann also nicht unbedingt noch irgend etwas anderes rein stecken, oder auf die Aufteilung verzichten. Man sollte halt nur nicht von Anfang an Module immer nur für eine Klasse vorsehen.

Wenn man eine Anwendung in einem Package hat, besteht das Startprogramm ausserhalb des Packages üblicherweise nur aus dem Import der `main()`-Funktion aus dem Package und deren Aufruf.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Krie9er
User
Beiträge: 22
Registriert: Montag 30. März 2020, 20:06

Nochmals vielen Dank für die Erklärung!

Ich nutze pyqt in erster Linie, da ich das so durch Kurse/Tutorials beigebracht bekommen habe. Hast du eventuell ein Tutorial für das die gui-Entwicklung ganz ohne pyqt erklärt? Wenn ja, dann giere ich auf den Link, da yt und die Udemykurse die ich bisher gesehen/genutzt habe immer nur den weg über pyqt gehen.

Bzgl. der Clusterung, mein Gedanke war eher pro klasse nur eine Datei zu haben. Ich werde jetzt jedoch nochmal meine Logik etwas umbauen, und auf das von dir beschriebene System umschwenken. Aktuell kämpfe ich allerdings noch mit den translation-tutorial für Qt, ich bin kurz davor einfach ein Dictionary aufzumachen oder mit gettext von Hand die Texte des Frontends umzuändern. Hier hat python/qt für python leider eine nicht ganz so gute Dokumentation. :-/

Vielen Dank für die guten Tipps und noch einen schönen Tag :-)
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Krie9er: Ohne `pyqt` würde man sich für eine der beiden Anbindungen von Qt an Python entscheiden, `PyQt5` oder `PySide2` und die direkt verwenden, statt über den Umweg mit `pyqt`. Das benutzt ja letztendlich auch nur eine dieser beiden Anbindungen. Beziehungsweise kann das auch noch `PyQt4` verwenden, aber damit würde ich kein neues Projekt mehr anfangen.

Die Entscheidung hängt in der Regel an der Lizenz. Und `pyqt` ist IMHO auch nur ein Hack um PyQt5 verwenden zu können ohne die Lizenz beachten zu müssen. Ist so ein bisschen Grauzone IMHO.

Falls man `PySide2` wählt ist das Laden von *.ui-Dateien etwas anders, weil das kein `uic`-Modul hat. Das muss man sich mit dem `QUiLoader` selber basteln. Ist aber auch nicht wirklich kompliziert.

Bei Anbindung an so umfangreiche Bibliotheken wie GUI-Rahmenwerke gibt es eigentlich nie eine umfassende Dokumentation für Python (oder auch andere Sprachen mit Anbindungen) weil es ja schon die Dokumentation für das GUI-Rahmenwerk selbst gibt. Und die von Qt ist ziemlich gut. Man muss dann nur noch ein bisschen C++ lesen lernen und wie die C++-API auf die Python-Anbindung abgebildet wird.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Krie9er
User
Beiträge: 22
Registriert: Montag 30. März 2020, 20:06

Ich bin auch nochmal zurück auf Anfang gegangen und habe nach neuem Lehrnmaterial gesucht. Da trifft es sich ganz gut, dass der RW-Verlag das Python-Openbook zur Verfügung stellt. Ich werde jetzt erstmal mit PyQt5 das angehen, und die ui zur Laufzeit laden. Tutorial. PySide werde ich mir dann als nächstes einmal ansehen.

Danke für das freundliche Feedback und die tollen Anmerkungen!
Antworten