Coder Perfect

In Python, check if an executable exists.


Is there a portable and easy technique to test if an executable program exists in Python?

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

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
        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: Added logic to handle the case where the provided argument is already a full path to the executable, such as “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. It appears that neither Windows nor POSIX encourages the use of quoted PATH.

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

Jan-Philip Gehrcke’s famous one-liner:

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

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. Note that on Windows, subprocess.Popen(exe, shell=True) will fail silently if exe is not found.

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