Problem
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
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: 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'
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. 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
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