Check if a program exists from a python script
shutil.which
Let me recommend an option that has not been discussed yet: a Python implementation of which
, specifically shutil.which
. It was introduced in Python 3.3 and is cross-platform, supporting Linux, Mac, and Windows. It is also available in Python 2.x via whichcraft. You can also just rip the code for which
right out of whichcraft here and insert it into your program.
def is_tool(name):
"""Check whether `name` is on PATH and marked as executable."""
# from whichcraft import which
from shutil import which
return which(name) is not None
distutils.spawn.find_executable
Another option that has already been mentioned is distutils.spawn.find_executable
.
find_executable
's docstring is as follows:
Tries to find 'executable' in the directories listed in 'path'
So if you pay attention, you'll note that the name of the function is somewhat misleading. Unlike which
, find_executable
does not actually verify that executable
is marked as executable, only that it is on the PATH. So it's entirely possible (however unlikely) that find_executable
indicates a program is available when it is not.
For example, suppose you have a file /usr/bin/wget
that is not marked executable. Running wget
from the shell will result in the following error: bash: /usr/bin/wget: Permission denied. which('wget') is not None
will return False, yet find_executable('wget') is not None
will return True. You can probably get away with using either function, but this is just something to be aware of with find_executable
.
def is_tool(name):
"""Check whether `name` is on PATH."""
from distutils.spawn import find_executable
return find_executable(name) is not None
The easiest way is to try to run the program with the desired parameters, and handle the exception if it doesn't exist:
try:
subprocess.call(["wget", "your", "parameters", "here"])
except FileNotFoundError:
# handle file not found error.
This is a common pattern in Python: EAFP
In Python 2, you had to catch OsError
instead, since the more fine-grained exception classes for OS errors did not exist yet:
try:
subprocess.call(["wget", "your", "parameters", "here"])
except OSError as e:
if e.errno == errno.ENOENT:
# handle file not found error.
else:
# Something else went wrong while trying to run `wget`
raise