904 Stimmen

Was ist die beste Projektstruktur für eine Python-Anwendung?

Stellen Sie sich vor, Sie möchten eine nicht-triviale Desktop-Anwendung (nicht Web-Anwendung) in Python für Endbenutzer entwickeln. Wie lässt sich die Ordnerhierarchie des Projekts am besten strukturieren?

Wünschenswerte Eigenschaften sind einfache Wartung, IDE-Freundlichkeit, Eignung für Source Control Branching/Merging und einfache Erzeugung von Installationspaketen.

Im Besonderen:

  1. Wo wird die Quelle angegeben?
  2. Wo werden Skripte zum Starten von Anwendungen abgelegt?
  3. Wohin kommt der IDE-Projektschrott?
  4. Wo platzieren Sie die Unit/Akzeptanztests?
  5. Wo legen Sie Nicht-Python-Daten wie Konfigurationsdateien ab?
  6. Wo legt man Nicht-Python-Quellen wie C++ für die binären Erweiterungsmodule von pyd/so ab?

31voto

KT. Punkte 9929

Versuchen Sie, das Projekt mit der Option python_boilerplate Vorlage. Sie folgt weitgehend den bewährten Verfahren (z. B. die hier ), eignet sich aber besser für den Fall, dass Sie Ihr Projekt irgendwann in mehr als ein Ei aufteilen wollen (und glauben Sie mir, das werden Sie bei allen Projekten tun, außer bei den einfachsten). Eine häufige Situation ist, dass Sie eine lokal modifizierte Version einer fremden Bibliothek verwenden müssen).

  • Wo wird die Quelle angegeben?

    • Bei größeren Projekten ist es sinnvoll, die Quelle in mehrere Eier aufzuteilen. Jedes Ei würde als separates setuptools-Layout unter PROJECT_ROOT/src/<egg_name> .
  • Wo werden Skripte zum Starten von Anwendungen abgelegt?

    • Ideal ist es, wenn das Startskript der Anwendung als entry_point in einem der Eier.
  • Wohin kommt der IDE-Projektschrott?

    • Hängt von der IDE ab. Viele von ihnen bewahren ihr Material in PROJECT_ROOT/.<something> in der Wurzel des Projekts, und das ist gut so.
  • Wo platzieren Sie die Unit/Akzeptanztests?

    • Für jedes Ei gibt es einen eigenen Satz von Tests, die in seinem PROJECT_ROOT/src/<egg_name>/tests Verzeichnis. Ich persönlich bevorzuge die Verwendung von py.test um sie zu betreiben.
  • Wo legen Sie Nicht-Python-Daten wie Konfigurationsdateien ab?

    • Es kommt darauf an. Es kann verschiedene Arten von Nicht-Python-Daten geben.
      • "Ressourcen" d.h. Daten, die in einem Ei verpackt werden müssen. Diese Daten werden in das entsprechende Ei-Verzeichnis, irgendwo im Paket-Namensraum, abgelegt. Sie können über die pkg_resources Paket von setuptools bzw. seit Python 3.7 über die importlib.resources Modul aus der Standardbibliothek.
      • "Konfigurationsdateien" , d.h. Nicht-Python-Dateien, die als extern zu den Projekt-Quelldateien zu betrachten sind, aber mit einigen Werten initialisiert werden müssen, wenn die Anwendung läuft. Während der Entwicklung ziehe ich es vor, solche Dateien in PROJECT_ROOT/config . Für die Bereitstellung stehen verschiedene Optionen zur Verfügung. Unter Windows kann man verwenden %APP_DATA%/<app-name>/config unter Linux, /etc/<app-name> o /opt/<app-name>/config .
      • Erstellte Dateien d.h. Dateien, die von der Anwendung während der Ausführung erstellt oder geändert werden können. Ich würde es vorziehen, sie in PROJECT_ROOT/var während der Entwicklung, und unter /var bei der Bereitstellung von Linux.
  • Wo legt man Nicht-Python-Quellen wie C++ für die binären Erweiterungsmodule von pyd/so ab?
    • In PROJECT_ROOT/src/<egg_name>/native

Die Dokumentation würde normalerweise in PROJECT_ROOT/doc o PROJECT_ROOT/src/<egg_name>/doc (dies hängt davon ab, ob Sie einige der Eier als separate Großprojekte betrachten). Einige zusätzliche Konfigurationen finden sich in Dateien wie PROJECT_ROOT/buildout.cfg y PROJECT_ROOT/setup.cfg .

0 Stimmen

Danke für die tolle Antwort! Sie haben viele Dinge für mich geklärt! Ich habe nur eine Frage: Können Eier verschachtelt werden?

0 Stimmen

Nein, man kann Eier nicht in dem Sinne "verschachteln", dass man .egg-Dateien in anderen .egg-Dateien speichert und hofft, dass dies von großem Nutzen ist [es sei denn, man hat etwas wirklich Seltsames vor]. Was Sie jedoch tun können, ist, "virtuelle" Eier zu erstellen - leere Pakete, die keinen nützlichen Code enthalten, aber andere Pakete in ihrer Abhängigkeitsliste aufführen. Wenn ein Benutzer versucht, ein solches Paket zu installieren, wird er auf diese Weise rekursiv viele abhängige Pakete installieren.

0 Stimmen

@KT können Sie ein wenig näher erläutern, wie Sie mit generierten Daten umgehen? Insbesondere, wie unterscheiden Sie (im Code) zwischen Entwicklung und Bereitstellung? Ich nehme an, Sie haben einige base_data_location Variable, aber wie setzt man sie richtig ein?

18voto

Jason Baker Punkte 180981

Meiner Erfahrung nach ist es nur eine Frage der Iteration. Legen Sie Ihre Daten und Ihren Code dorthin, wo sie Ihrer Meinung nach hingehören. Die Chancen stehen gut, dass Sie sich trotzdem irren werden. Aber sobald Sie eine bessere Vorstellung davon haben, wie sich die Dinge entwickeln werden, sind Sie in einer viel besseren Position, um diese Art von Vermutungen anzustellen.

Was die Quellen für Erweiterungen angeht, so haben wir ein Code-Verzeichnis unter trunk, das ein Verzeichnis für Python und ein Verzeichnis für verschiedene andere Sprachen enthält. Ich persönlich bin eher geneigt, beim nächsten Mal zu versuchen, jeden Erweiterungscode in ein eigenes Repository zu packen.

Damit komme ich auf meinen anfänglichen Punkt zurück: Machen Sie nicht zu viel Aufhebens davon. Legen Sie es an einen Ort, der für Sie geeignet ist. Wenn Sie etwas finden, das nicht funktioniert, können (und sollten) Sie es ändern.

0 Stimmen

Ja, das stimmt. Ich versuche, es "pythonisch" zu sehen: explizit ist besser als implizit Verzeichnishierarchien werden mehr gelesen/geprüft als sie geschrieben werden. Etc..

14voto

Charles Duffy Punkte 255246

Nicht-Python-Daten werden am besten innerhalb Ihrer Python-Module gebündelt, indem Sie die package_data Unterstützung bei setuptools . Eine Sache, die ich dringend empfehle, ist die Verwendung von Namespace-Paketen, um gemeinsam genutzte Namespaces zu erstellen, die von mehreren Projekten verwendet werden können - ähnlich wie die Java-Konvention, Pakete in com.yourcompany.yourproject (und die Möglichkeit, eine gemeinsame com.yourcompany.utils Namespace).

Re Verzweigung und Zusammenführung, wenn Sie eine gute genug Quellcode-Kontrollsystem verwenden, wird es Zusammenführungen auch durch Umbenennungen verarbeiten; Basar ist besonders gut in diesem Bereich.

Im Gegensatz zu einigen anderen Antworten hier, bin ich +1 auf eine src Verzeichnis der obersten Ebene (mit doc y test Verzeichnisse daneben). Die spezifischen Konventionen für Dokumentationsverzeichnisbäume variieren je nach dem, was Sie verwenden; Sphinx hat zum Beispiel seine eigenen Konventionen, die das Schnellstartprogramm unterstützt.

Bitte, bitte nutzen Sie setuptools und pkg_resources; das macht es für andere Projekte viel einfacher, sich auf bestimmte Versionen Ihres Codes zu verlassen (und für mehrere Versionen, die gleichzeitig mit verschiedenen Nicht-Code-Dateien installiert werden, wenn Sie package_data ).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X