Wie mit ausführbarer Datei für eigene Bibliothek umgehen?

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
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich habe meinem Projekt Launchit nun eine ausführbare Datei spendiert, welche einfach ein Python-Skript ohne `.py`-Endung ist und im Verzeichnis `bin` direkt unterhalb des Wurzelverzeichnisses liegt. Dieses Skript führt letztlich die `gui.main()` aus.

Da es derzeit noch kein Installationsskript für das Paket gibt und weil ich auch später den Anwender nicht dazu zwingen möchte, Launchit komplett zu installieren, wenn er es eigentlich nur mal aus dem Repo zum Ausprobieren aufrufen will, behelfe ich mir mit ein paar Zeilen zusätzlichem Code, um Launchit importieren zu können, obwohl die besagte Datei selbst nicht Teil eines Pakets ist (keine `__init__.py`). Dazu setze ich beim Aufruf des Executables einfach das darüberliegende Verzeichnis an den Anfang von `sys.path` und mache den Import von Launchit anschließend.

So weit, so gut. Was mich jetzt aber stört, ist der Gedanke, wenn es das Skript irgendwann mal als installierte Variante a la `/usr/bin/launchit` gibt. In diesem Fall würde es unsinnigerweise das darüberliegende Verzeichnis `/usr` in `sys.path` setzen, was von Pythons Import-Mechanismus zwar lautlos übergangen werden müsste, aber ja irgendwie trotzdem doof ist. Gibt es dafür irgendein besseres Vorgehen? Ist vielleicht auch meine Idee an sich schon blöde?

Ich freue mich auf eure Vorschläge. :)

Achso, hier die Umsetzung zum Zeitpunkt als der Beitrag verfasst wurde: https://github.com/seblin/launchit/blob ... n/launchit
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Ich würde einfach direkt versuchen launchit zu importieren

Code: Alles auswählen

#!/usr/bin/env python
try:
    import launchit
except ImportError:
    def add_dev_path():
        import os, sys
        module_dir = os.path.dirname(__file__)
        new_path = os.path.join(module_dir, "..")
        sys.path.append(package_path)
    add_dev_path()    
    import launchit

launchit.gui.main()
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Darii: Dann würde das Executable grundsätzlich die installierte Version von Launchit benutzen, sobald eine vorhanden ist. Das möchte ich eigentlich vermeiden, da es sicher irritierend wäre, wenn jemand irgendwann mal ein Release von Launchit installiert hätte und 3 Monate später den Stand im Repo testen möchte. Denn auch wenn Python-Importe an sich anderen Regeln folgen, so würde ich als unbedarfter User schon erwarten, dass ein "Binary" diejenige Version einer Bibliothek benutzt, zu der es sozusagen gehört.

//edit: Blödsinn. Auch Python-Importe bevorzugen natürlich lokale Modul-Namen vor globalen Namen, da das aktuelle Verzeichnis ja standardmäßig ganz am Anfang des Python-Path steht und damit auch zuerst durchsucht wird. :oops:
Zuletzt geändert von snafu am Sonntag 31. Juli 2011, 14:58, insgesamt 1-mal geändert.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dann dreh die Logik halt um und mach ein os.path.exists vor dem sys.path.append
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich prüfe jetzt einfach, ob der übergeordnete Pfad ein Unterverzeichnis namens `launchit` hat und setze den übergeordneten Pfad nur dann ein:

Code: Alles auswählen

path = os.path.join(os.path.dirname(__file__), '..')
if os.path.isdir(os.path.join(path, 'launchit')):
    sys.path.insert(0, os.path.abspath(path))

import launchit
launchit.gui.main()
Die Annahme "Ein-Paket-Ist-Ein-Verzeichnis" halte ich erstmal für ausreichend. Wir wollen ja nicht übertreiben. :)
Antworten