Seite 1 von 1
path variable testen (bash)
Verfasst: Montag 3. September 2012, 13:14
von RedSharky
Hallo,
ich möchte testen, ob ein externes Programm über eine Path Variable angesprochen und ausgeführt werden kann (ansonsten soll der User einen validen Pfad angeben).
Ich habe es mit os.access, os.path.isfile ausprobiert; beides immer False.
Man man bräuchte ein Python-Äquivalent von `which`, z.B.: `which mybinary`
/usr/bin/mybinary
Mir fällt bis jetzt nur ein, ein Shell-Commando abzusetzen, aber das ist doch doof, oder?
Danke!
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 13:39
von deets
Wieso ist es doof, ein Shell-Befehl auszufuehren, wenn du danach eben einen Shell-Befehl ausfuehren willst? Du verlaesst dich auf die Semantik eines Subprozesses, und wie dessen Aufruf mit der PATH-Variable umgeht. Dann benutzt das doch.
Externe Kommandos sind nur dann "doof", wenn man ihre Existenz nicht voraussetzen kann (und "which" sollte es geben...), oder das was sie tun zu Ineffizienz fuehrt ("sort" aufrufen, um eine Liste von Strings zu sortieren... oder sowas).
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 15:39
von snafu
@deets: Ich sehe jetzt nicht wirklich, wo etwas von "Shell-Befehl absetzen" steht. Die Aufgabenstellung scheint eher zu sein, ob zu einem angegebenen Programmnamen die passende ausführbare Datei im `PATH` gefunden wird und zwar ohne ein tatsächliches Ausführen des Programms zu probieren. Da kann man IMHO durchaus sagen, dass man es plattformunabhängig halten will und `which` lieber vermeidet.
Mein Vorschlag:
Code: Alles auswählen
import os
def which(command):
basedirs = os.getenv('PATH', '').split(os.pathsep)
for basedir in basedirs:
path = os.path.join(basedir, command)
if os.path.isfile(path) and os.access(path, os.X_OK):
return path
Wobei der zusätzliche Test auf Ausführbarkeit AFAIK beim "normalen" `which` nicht besteht.
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 15:57
von deets
@snafu:
Das war genau das was ich meinte: du hast jetzt etwas implementiert, von dem du *glaubst*, es ist das richtige Verhalten. Ich bezweifele nicht, dass es dem "Original" recht nahe kommt. Aber wissen wir's? Nee. Ob da zB Pfad-Normalisierung dabei sind usw.
So wie du zB 100%ig nicht gewusst hast, dass "which" die Ausfuehrbarkeit bereits testet.
Wo ist also der Gewinn von deinen 7 Zeilen Code gegen ein simples
Code: Alles auswählen
if subprocess.call(["wich", command) == 1:
print "Kommando", command, "existiert nicht"
?
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 16:23
von cofi
deets hat geschrieben:Wo ist also der Gewinn von deinen 7 Zeilen Code gegen ein simples ... ?
Man kann `which' nicht falsch schreiben
Fuer mich sieht es aber so aus, als ob der OP einfach den Fall abfangen wird, dass ein Programm nicht gefunden wird und dann den User befragt. Was spricht hier gegen ein Abfangen des `OSError`?
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 16:36
von deets
Tippfehler gilden nicht...
Natuerlich kann man den OSError abfangen, aber zum einen ist der unspezifischer - welcher genau ist jetzt der richtige, bzw. koennen welche fliegen, die nichts mit der nicht-existenz des Kommandos zu tun haben?
Und so wie ich den OP verstanden habe, geht es eher um sowas wie ne Konfiguration. Man will *vorher* wissen, ob's was bestimmtes gibt, und wenn nicht, dann muss der User das erstmal richtig konfigurieren. Und weil nicht jedes Kommando seiteneffektfrei daher kommt, finde ich das which (mit 2 h) auch ok.
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 16:57
von lunar
@deets "which" ist eine ziemlich dumme Idee. Man kann sich nämlich weder auf das Ausgabeformat noch überhaupt auf die Existenz dieses Kommandos verlassen. Um "which" zu verwenden, ob die Existenz eines Kommandos zu prüfen, müsste man also erstmal prüfen, ob "which" existiert. Du verstehst?
Auf der anderen Seite ist in POSIX ziemlich klar spezifiziert, wie "$PATH" zu interpretieren und wie Kommandos über "$PATH" aufzulösen sind. Dort kann man nachlesen, dass die Prozedur ziemlich einfach ist, und insbesondere keine „Pfad-Normalisierung“ vorsieht. snafus Implementierung ist zwar nicht richtig, aber nahe dran:
Code: Alles auswählen
def is_command(command):
return all(s not in command for s in filter(None, (os.sep, os.altsep)))
def resolve_command(command):
if not is_command(command):
raise ValueError(command)
directories = (d or os.getcwd() for d in os.environ['PATH'].split(os.pathsep))
candidates = (os.path.join(d, command) for d in directories)
executables = (c for c in candidates if os.path.isfile(c) and os.access(c, os.X_OK))
executable = next(executables, None)
if not executable:
raise LookupError(command)
else:
return command
def find_executable(command):
if is_command(command):
return resolve_command(command)
else:
return os.path.abspath(command)
Unter Windows ist das zwar ein bisschen komplizierter, weil "$PATHEXT" zu berücksichtigen ist, doch Windows hat ohnehin kein "which".
Ich persönlich würde das aber einfach sein lassen, und OSError abfangen, wie cofi vorgeschlagen hat. Klar hast Du recht, der "OSError"
kann vielleicht auch eine andere Ursache haben. Doch was immer die Ursache sein mag, die Auswirkungen sind dieselben: Das Kommando kann nicht ausgeführt werden.
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 20:57
von deets
lunar hat geschrieben:@deets "which" ist eine ziemlich dumme Idee. Man kann sich nämlich weder auf das Ausgabeformat noch überhaupt auf die Existenz dieses Kommandos verlassen. Um "which" zu verwenden, ob die Existenz eines Kommandos zu prüfen, müsste man also erstmal prüfen, ob "which" existiert. Du verstehst?
Soso, eine ziemlich dumme Idee. Hast du ein Beispiel fuer ein real existierendes Unix auf dem das *nicht* existiert, oder ist das nur ein Argument um des Argumentes willen? Der OP scheint sich jedenfalls auf Unix zu beziehen, von Plattformunabhaengigkeit war erstmal nicht die Rede.
Und hast du in meinem Code-Snippet etwas von Ausgabe-verarbeitung gesehen? Ich verwende den Rueckgabewert...
Ich persönlich würde das aber einfach sein lassen, und OSError abfangen, wie cofi vorgeschlagen hat. Klar hast Du recht, der "OSError" kann vielleicht auch eine andere Ursache haben. Doch was immer die Ursache sein mag, die Auswirkungen sind dieselben: Das Kommando kann nicht ausgeführt werden.
Ich persoenlich halte *das* fuer eine ziemlich dumme Idee, denn schliesslich mag dieser OSError am Ende einer langen Kette von externen Programmaufrufen stehen, welche bis dahin schon eine Menge an Seiteneffekten produziert haben - und dann steht deine Anwendung in einem modalen Dialog oder ist abgebrochen, statt ueber Nacht deine Daten zu crunchen. Das haette *ich* dann gerne vorher gewusst
Aber dumme Ideen liegen ja auch im Auge des Betrachters.
Re: path variable testen (bash)
Verfasst: Montag 3. September 2012, 22:00
von snafu
Der Weg über `OSError` hätte halt den Nachteil, dass das Programm, wenn es existiert, dann auch erstmal ausgeführt wird, was unter Umständen nicht gewünscht ist (kenne die Rahmenbedingungen ja nicht).
Aber bevor ich mir irgendein höchst POSIX-konformes `which` bastle (und ich Wert darauf lage, dass dies erfüllt wird), würde ich wahrscheinlich auch lieber `which` direkt ausführen.
Mein eigener Ansatz mag jetzt nicht 1:1 übereinstimmen (mangels Kenntnisse über den Standard), aber deckt IMHO die eigentliche Problemstellung ganz gut ab.
Also ich würde ja sagen: Entweder ein nicht ganz perfektes nachgemachtes `which` oder eben ein "echtes" `which`, sofern davon ausgegangen werden kann, dass nur unixoide Plattformen genutzt werden, wo `which` mutmaßlich immer vorhanden ist. Alles andere wird mir persönlich zu absurd.
Re: path variable testen (bash)
Verfasst: Dienstag 4. September 2012, 08:26
von RedSharky
Danke für die vielen fundierten Hinweise! Ich denke, ich werde doch "which" benutzen. Ausführen des Programmes will ich auf jeden Fall vermeiden, da es etwas bescheuert programmiert ist (hatte ich nicht erwähnt).
Danke nochmal!!!