Wohin mit INI-Dateien, Grafiken, ...?
Dies ist erst einmal nur eine Richtlinie, und noch kein ausgearbeitetes Rezept. Sie entstand als Ergebnis der Diskussionen in der Newsgroup de.comp.lang.python im Thread Wohin mit INI-, Daten-, ... Dateien?
Mag das jemand ins Englische übersetzen und nach comp.lang.python bringen? Lohnt sich das hier bereits als PEP? Auf jeden Fall stecken schon viele gute Ideen drin.
Wer nicht die distutils, sondern setuputils/pkg_resources verwendet, sollte dieser Anleitung nicht folgen, und stattdessen PythonEggs - Accessing Package Resources lesen.
Einleitung
Kein größeres Python-Programm besteht nur noch aus Python-Quellcode. Es kommen viel mehr Dateien hinzu, die ich grundsätzlich in folgende Kategorien einteile:
- systemweite Dateien
- platformspezifischer Code
- (z.B. in C geschriebene, compilierte Module)
- Python-Code
- nur-lesbare Dateien
- Konfiguration
- Daten
- Grafiken
- Templates
- Musik
- ...
- schreibbare Dateien
- Logdateien
- Datenbanken
- ...
- platformspezifischer Code
- benutzerspezifische Dateien
- Konfiguration (benutzerspezifisch)
- eigene Levels, Highscores (bei Spielen)
- eigene Templates (bei Textverarbeitung)
- ...
Die Python-Distutils unterstützen uns nur in den Bereichen:
- platformspezifischer Code
- (z.B. in C geschriebene, compilierte Module)
- Python-Code
Der Artikel Profilpfad herausfinden erschlägt den Bereich:
- benutzerspezifische Dateien
- Konfiguration (benutzerspezifisch)
- eigene Levels, Highscores (bei Spielen)
- eigene Templates (bei Textverarbeitung)
- ...
Bleiben also die systemweiten externen Dateien übrig:
- nur-lesbare Dateien
- Konfiguration
- Daten
- Grafiken
- Templates
- Musik
- ...
- schreibbare Dateien
- Logdateien
- Datenbanken
- ...
Hierbei gibt es einen qualitativen Unterscheid: Für die nur-lesbaren Dateien braucht man höchstens zwei Verzeichnisse, Konfiguration und Daten. Aber die schreibbaren Dateien können sehr viele sehr unterschiedliche Verzeichnisse benötigen, sollten also auf jeden Fall nachträglich einstellbar sein.
An das System gibt es noch folgende Ansprüche:
- Eine Applikation soll sowohl aufgedröselt auf viele Verzeichnisse funktionieren ("installiert"), als auch kompakt in einem einzigen Verzeichnis. ("ZIP-Datei entpacken und starten")
- Keinen Pfad fest verdrahten!
- Dies alles soll dynamisch funktionieren, ohne dass man beim Compilieren/Installieren irgendwie den Programmcode anfassen muss.
- Kein blindes Ausprobieren von mehreren Pfaden!
- Trotz der Dynamik sollte jederzeit genau feststehen, welche Datei wo gesucht wird.
Richtlinie
- Um C-Code und Python-Code kümmern sich die Python-Distutils.
- Sie können den C-Code compilieren, und die compilierten Module werden auf jeden Fall gefunden, egal ob man das Programm direkt im Source-Verzeichnis startet, oder ob man es vorher installiert. Diese Sorgen nimmt uns Python ab.
- Alle anderen Pfade zu externen Dateien werden zur Laufzeit ermittelt.
- Hierzu empfielt sich ein Applikations-Modul "config.py", das beim Start diese Pfade ermittelt und dem Rest der Applikation zur Verfügung stellt. Eventuell enthält config.py auch einige Hilfsfunktionen.
- Auf keinen Fall werden in den C-Code feste Pfade eincompiliert oder Such-Aktionen durchgeführt.
- Der C-Code nutzt entweder über die Python-API das config.py-Modul, oder erhält die Pfade als Funktions-Parameter. Allein das config.py-Modul ermittelt die Pfade.
config.py ermittelt das Verzeichnis für die benutzerspezifischen Dateien über die Funktion get_settings_folder()
(siehe Profilpfad herausfinden)
- config.py ermittelt außerdem das Verzeichnis, in dem der Python-Code liegt:
_prefix = os.path.dirname(os.path.abspath(__file__))
Von _prefix ausgehend kann man zwei Richtungen vorstoßen:
Man erwartet all seine Dateien in den Unterverzeichnissen von _prefix.
- Sollten sie woanders im System liegen müssen, hat der Administrator entsprechende Verknüpfungen (Symlinks) zu setzen.
Man holt sich von _prefix ausgehend eine Konfigurations-Datei "path.ini".
- In dieser stehen alle interessanten Pfade, und können vom Administrator ggf. angepasst werden. Die angegebenen Pfade können relativ oder absolut sein,
os.path.join(_prefix, pfad_aus_path_ini) wird in beiden Fällen korrekt funktionieren.
- In dieser stehen alle interessanten Pfade, und können vom Administrator ggf. angepasst werden. Die angegebenen Pfade können relativ oder absolut sein,
Was fehlt noch?
- Ein konkretes Design
- Welche Konfigurations-Datei enthält was? Wo kommen Symlinks hin, wo nicht?
- Eventuell ein Modul, das einem beim Programmieren der config.py hilft.
(viele kleine Hilfsfunktionen? eine große PathConfig-Klasse?)
- Ein konkretes Programm, das all diese Richtlinien erfolgreich umsetzt.
- Ein schöner Titel. Das heißt, eine gut klingende, selbsterklärende, englische Überschrift.