Python: Gemeinsamen Code unter einer Familie von Skripten teilen

Ich schreibe eine Familie von Python-Skripten in einem Projekt; Jedes Skript befindet sich in einem Unterverzeichnis des Projekts, so wie:

projectroot | |- subproject1 | | | |- script1.main.py | `- script1.merger.py | |- subproject2 | | | |- script2.main.py | |- script2.matcher.py | `- script2.merger.py | `- subproject3 | |- script3.main.py |- script3.converter.py |- script3.matcher.py `- script3.merger.py 

Jetzt einige der Skripte teilen einige Code. Der geteilte Code ist am besten als Teil des Projekts selbst, und nicht etwas, was ich kompilieren würde separat und machen eine Bibliothek aus, oder fallen in einem sitewide PYTHONPATH. Ich könnte diesen Code an verschiedenen Orten platzieren, wie projectroot im projectroot Verzeichnis selbst oder in einem projectroot Verzeichnis von projectroot als common (vielleicht) bezeichnet wird.

Allerdings haben die meisten der Art und Weise, die ich bisher gedacht habe, die Herstellung von Paketen aus meinen Teilprojekten mit leeren __init__.py Dateien und mit relativen Importen (oder redundant sys.path mit sys.path in jedem Teilprojekt. Schlimmer noch, es scheint wie das sys.path Um diese Familie von Skripten läuft die folgende Warnung aus dem abgelehnten PEP-32122:

Aufmerksamkeit! Dieser PEP wurde abgelehnt. Guido sieht laufende Skripte innerhalb eines Pakets als Anti-Muster.

Wenn Skripte innerhalb eines Pakets Anti-Muster sind, wie kann ich die Dinge in einer Weise, die den gemeinsamen Code in dem gleichen Projekt hält? Oder ist ein Modul und Paket-basiertes System hier akzeptabel? Welches ist der sauberste Ansatz? (FWIW würde ich lieber eine Datei wie shared.py oder common.py im Projekt-Stammverzeichnis haben, anstatt ein Utility-Verzeichnis zu common.py , das ein Geschwister für die "realen" Teilprojekte ist.)

3 Solutions collect form web for “Python: Gemeinsamen Code unter einer Familie von Skripten teilen”

Ich schlage vor, triviale "Launcher" -Skripte auf der obersten Ebene deines Projekts zu setzen und jedes der Unterprojektordner in Pakete zu machen. Die Module in den Paketen können einander importieren oder der gemeinsame Code kann in ein common Paket eingegeben werden.

Hier ist, wie die Struktur aussehen würde, wenn wir davon ausgehen, dass die verschiedenen Fusionsmodule in eine gemeinsame Version umgestaltet werden können:

 projectroot |- script1.py # launcher scripts, see below for example code |- script2.py |- script3.py | |- common | |- __init__.py | |- merger.py # from other packages, use from ..common import merger to get this | |- subproject1 | |- __init__.py # this can be empty | |- script1_main.py | |- subproject2 | |- __init__.py | |- script2_main.py | |- script2_matcher.py | |- subproject3 |- __init__.py |- script3_main.py |- script3_converter.py |- script3_matcher.py 

Die Launcher-Skripte können ganz einfach sein:

 from subproject1 import script1_main if __name__ == "__main__": script1_main.main() 

Das ist alles, was es tut, ist das entsprechende "scriptN_main" -Modul importieren und eine Funktion ausführen. Die Verwendung eines einfachen Skripts kann auch einige kleine Vorteile für die Skript-Startgeschwindigkeit haben, da das Hauptmodul seinen kompilierten Bytecode in einer .pyc Datei zwischengespeichert .pyc kann, während Scripts niemals zwischengespeichert werden.

Anmerkung: Ich habe Ihre Module umbenannt und die Zeichen für die . Figuren. Du kannst kein . In einem Bezeichner (wie zB ein Modulname), da Python davon ausgeht, dass er den Attributzugriff angibt. Das bedeutete, dass diese Module niemals importiert werden konnten. (Ich vermute, dass dies ein Artefakt der Beispiel-Dateien nur ist, nicht etwas, was Sie in Ihrem echten Code haben.)

Meine Präferenz wäre ein separates "bin" oder "scripts" Verzeichnis, mit Teilprojekten als Bibliotheken / Pakete:

 projectroot | |- scripts | |- lib | | | `- matcher.py | `- merger.py | `- subproject1 | `- subproject2 | `- subproject3 

Die Idee, die Ihre Skripte sind, kann jeweils auf Unterprojekte hinweisen, die als übliche Pakete erforderlich sind. Und Ihre Teilprojekte können sich auch mit Importen verweisen.

Sie können dann auch ein Haupt- oder gemeinsames Skript haben, das die Unterprojektpakete für Sie einrichtet, falls das hilft.

Bitte verwenden Sie setuptools , um beide Skripts und Bibliotheken zu verteilen:

z.B

 from setuptools import setup setup( # other arguments here... (eg packages / package_dir) entry_points = { 'console_scripts': [ 'script1 = subproject1.script1:main', 'script2 = subproject2.script2:main', ], } ) 

Wenn Sie alle schreiben können, die Sie als Bibliotheken kodieren, und brauchen keine separaten Module, um Ihre Einstiegspunkte zu haben, dann ist dies das Werkzeug für Sie. Wenn Sie Skripte haben, ist das auch gut, aber Sie benötigen eine main , die Sie verweisen können (siehe Beispiel oben)

  • Python os.path.commonprefix - gibt es eine wegorientierte Funktion?
  • PyCharm aktuelles Arbeitsverzeichnis
  • Python-Pythonpath-Module installieren
  • Wie konvertiere ich ~ /. Weg zum absoluten Weg
  • Einstellpfad im Terminal
  • Probleme mit PYTHONPATH
  • Importfehler: Kein Modul namens django
  • Finden Sie den vollständigen Pfad des Python-Interpreters?
  • Wie bekomme ich den Pfad der aktuell ausgeführten Datei in Python?
  • Wie kann ich den Weg des laufenden Skripts in Python kennen?
  • Fehlerbehebung python sys.path
  • Python ist die beste Programmiersprache der Welt.