Coder Perfect

In Python, check if an executable exists.

Problem

Is there a rogram?

By simple, I’m referring to something like the which command, which would be ideal. I don’t want to manually search PATH or try to run it with Popen & al to see if it fails (which is what I’m doing right now, but assume it’s launchmissiles).

Asked by Piotr Lesnicki

Solution #1

You can use distutils.spawn.find executable, which I know is an old question. Since python 2.4, this has been documented, and it has existed since python 1.6.

import distutils.spawn
distutils.spawn.find_executable("notepad.exe")

Shutil is now available in Python 3.3. which().

Answered by Nathan Binkert

Solution #2

The simplest method I can think of is:

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["PATH"].split(os.pathsep):
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None

Edit: Updated code sample to include logic for handling case where provided argument is already a full path to the executable, i.e. “which /bin/ls”. This behaves similarly to the UNIX ‘which’ command.

As a result of the comments, I’ve changed the code to use os.path.isfile() instead of os.path.exists().

Edit: path.strip(‘”‘) appears to be the incorrect action here. Quoted PATH entries do not appear to be encouraged by either Windows or POSIX.

Answered by Jay

Solution #3

Use the Python standard library’s shutil.which() function. There are batteries included!

Answered by Dr. Jan-Philip Gehrcke

Solution #4

import shutil

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

As a one-liner of Jan-Philip Gehrcke Answer:

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

As a def:

def cmd_exists(cmd):
    return shutil.which(cmd) is not None
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)
)

Jay’s Answer is a one-liner, which is also available as a lambda func:

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')

Last but not least, indented as a function:

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

Answered by 5 revs, 3 users 97%

Solution #5

On Windows, just remember to give the file extension. Otherwise, you’ll have to use the PATHEXT environment option to construct a far more sophisticated is exe for Windows. You could simply use FindPath.

However, why are you looking for the executable in the first place? The operating system will do it for you as part of the popen call, and if the executable is not found, an exception will be raised. All you have to do is catch the appropriate OS exception. If exe is not found on Windows, subprocess.Popen(exe, shell=True) will fail quietly.

Including PATHEXT in the above implementation, which (according to Jay):

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

Answered by Suraj

Post is based on https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python