377 Stimmen

Überprüfen Sie, ob eine ausführbare Datei in Python vorhanden ist?

In Python gibt es eine portable und einfache Möglichkeit zu testen, ob ein ausführbares Programm existiert?

Mit einfach meine ich etwas wie den which-Befehl, der einfach perfekt wäre. Ich möchte nicht manuell im PATH suchen oder etwas probieren, das versucht, es mit Popen & Co. auszuführen und zu sehen, ob es fehlschlägt (das ist das, was ich gerade mache, aber stelle dir vor, es ist launchmissiles)

4 Stimmen

Was ist falsch daran, nach der PATH-Umgebungsvariablen zu suchen? Was denkst du, was das UNIX-Befehl 'which' tut?

1 Stimmen

Ist das which.py Skript aus der Standardbibliothek ein einfacher Weg?

0 Stimmen

@J.F. - Das which.py-Skript, das mit Python enthalten ist, hängt von 'ls' ab, und einige der anderen Kommentare deuten darauf hin, dass Piotr nach einer plattformübergreifenden Antwort gesucht hat.

389voto

Nathan Binkert Punkte 8448

Die Python-Standardbibliothek bietet jetzt shutil.which an.

338voto

Jay Punkte 40418

Einfachste Möglichkeit, die mir einfällt:

def which(program):
    import os
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ.get("PATH", "").split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None

Bearbeiten: Aktualisierter Code mit Logik zur Behandlung des Falls, wenn das bereitgestellte Argument bereits ein vollständiger Pfad zur ausführbaren Datei ist, d.h. "which /bin/ls". Dies ahmt das Verhalten des Unix-Befehls 'which' nach.

Bearbeiten: Aktualisierung zur Verwendung von os.path.isfile() anstelle von os.path.exists() gemäß Kommentaren.

Bearbeiten: path.strip('"') scheint hier falsch zu sein. Weder Windows noch POSIX scheinen dazu zu ermutigen, PATH-Elemente in Anführungszeichen zu setzen.

275voto

Verwenden Sie shutil.which() aus der wunderbaren Python-Standardbibliothek.

Dokumentiert als

Gibt den Pfad zu einer ausführbaren Datei zurück, die ausgeführt würde, wenn der angegebene Befehl aufgerufen würde. Wenn kein Befehl aufgerufen würde, wird None zurückgegeben.

import shutil

path = shutil.which("foo") 

if path is None:
    print("Keine ausführbare Datei für Befehl 'foo' gefunden")
else:
    print(f"Pfad zur ausführbaren Datei 'foo': {path}")

Vorteile gegenüber selbstgemachten Lösungen: Dokumentation, Interface-Stabilität, langfristige Wartung. Ich habe vor ungefähr 10 Jahren hier für diese Lösung plädiert, und erst vor einem Monat (April 2023) wurden wieder einige relevante Details unter der Haube dieser von ausgezeichneten Ingenieuren bereitgestellten High-Level-Schnittstelle verbessert. Alles inklusive!

Übrigens, der Name stammt tatsächlich vom berühmten which-Befehl auf Unix-ähnlichen Systemen (und der penible POSIX-Person sagt: "Verwenden Sie niemals which cmd, verwenden Sie command -v cmd, das ist portabler") :-).

82voto

ThorSummoner Punkte 13974

Für Python 3.3 und höher:

import shutil

command = 'ls'
shutil.which(command) is not None

Als Einzeiler von Jan-Philip Gehrcke Antwort:

cmd_exists = lambda x: shutil.which(x) is not None

Als Funktion:

def cmd_exists(cmd):
    return shutil.which(cmd) is not None

Für Python 3.2 und früher:

my_command = 'ls'
any(
    (
        os.access(os.path.join(path, my_command), os.X_OK) 
        and os.path.isfile(os.path.join(path, my_command)
    )
    for path in os.environ["PATH"].split(os.pathsep)
)

Dies ist ein Einzeiler von Jay's Antwort, auch hier als Lambda-Funktion:

cmd_exists = lambda x: any((os.access(os.path.join(path, x), os.X_OK) and os.path.isfile(os.path.join(path, x))) for path in os.environ["PATH"].split(os.pathsep))
cmd_exists('ls')

Oder schließlich eingerückt als Funktion:

def cmd_exists(cmd, path=None):
    """ test if path contains an executable file with name
    """
    if path is None:
        path = os.environ["PATH"].split(os.pathsep)

    for prefix in path:
        filename = os.path.join(prefix, cmd)
        executable = os.access(filename, os.X_OK)
        is_not_directory = os.path.isfile(filename)
        if executable and is_not_directory:
            return True
    return False

21voto

Suraj Punkte 4649

Denken Sie einfach daran, die Dateierweiterung unter Windows anzugeben. Andernfalls müssen Sie einen viel komplizierteren is_exe für Windows unter Verwendung der Umgebungsvariable PATHEXT schreiben. Sie möchten vielleicht einfach FindPath verwenden.

Andererseits, warum suchen Sie überhaupt nach dem ausführbaren Programm? Das Betriebssystem wird dies für Sie als Teil des popen-Aufrufs erledigen und eine Ausnahme auslösen, wenn das ausführbare Programm nicht gefunden wird. Alles, was Sie tun müssen, ist die richtige Ausnahme für das jeweilige Betriebssystem abzufangen. Beachten Sie, dass unter Windows subprocess.Popen(exe, shell=True) still scheitern wird, wenn exe nicht gefunden wird.


Integration von PATHEXT in die obige Implementierung von which (in Jays Antwort):

def which(program):
    def is_exe(fpath):
        return os.path.exists(fpath) and os.access(fpath, os.X_OK) and os.path.isfile(fpath)

    def ext_candidates(fpath):
        yield fpath
        for ext in os.environ.get("PATHEXT", "").split(os.pathsep):
            yield fpath + ext

    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            for candidate in ext_candidates(exe_file):
                if is_exe(candidate):
                    return candidate

    return None

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