Put another way, is there a cross-platform way of knowing which file will be executed by subprocess.Popen(file)
without first executing it?

- 16,328
- 12
- 61
- 75
-
2https://github.com/amoffat/pbs/blob/master/pbs.py#L95 – Josh Lee Mar 26 '12 at 18:21
-
By default, subprocess inherents the environment of the parent process. So for any executable in the PATH (or the OS in question's equivalent) you don't need to specifiy the location. – Roland Smith Mar 26 '12 at 20:12
-
@JoshLee looks like PBS is no longer available. – Joe Jun 03 '13 at 19:16
-
1https://github.com/amoffat/sh/blob/master/sh.py#L162 – Josh Lee Jun 03 '13 at 19:40
3 Answers
Python 3.3 added shutil.which()
to provide a cross-platform means of discovering executables:
http://docs.python.org/3.3/library/shutil.html#shutil.which
Return the path to an executable which would be run if the given cmd was called. If no cmd would be called, return None.
Sample calls:
>>> shutil.which("python")
'/usr/local/bin/python'
>>> shutil.which("python")
'C:\\Python33\\python.EXE'
Unfortunately, this has not been backported to 2.7.x.

- 19,579
- 7
- 67
- 84
-
4Python source for version 3.3's implementation of shutil.which is here (only a few dozen lines): http://hg.python.org/cpython/file/6860263c05b3/Lib/shutil.py#l1068 – joemaller Jun 10 '13 at 13:53
-
2if you change line 1110 to `if any([cmd.lower().endswith(ext.lower()) for ext in pathext])` (turn the generator to a list) than it will work in python 2.7. – Chris Hagmann Apr 11 '14 at 13:01
-
3
-
-
3
An option for Python 2 and 3:
from distutils.spawn import find_executable
find_executable('python') # '/usr/bin/python'
find_executable('does_not_exist') # None
find_executable(executable, path=None)
simply tries to find 'executable' in the directories listed in 'path'. Defaults to os.environ['PATH']
if 'path' is None
. Returns the complete path to 'executable' or None
if not found.
Keep in mind that unlike which
, find_executable
does not actually check that the result is marked as executable. You may want to call os.access(path, os.X_OK)
to check that on your own if you want to be certain that subprocess.Popen
will be able to execute the file.
Also of note, shutil.which
of Python 3.3+ has been backported and made available for Python 2.6, 2.7, and 3.x via the 3rd-party module whichcraft.
It is available for installation via the aforementioned GitHub page (i.e. pip install git+https://github.com/pydanny/whichcraft.git
) or the Python package index (i.e. pip install whichcraft
). It can be used like such:
from whichcraft import which
which('wget') # '/usr/bin/wget'

- 5,122
- 3
- 29
- 38
-
1Avoid distutils because it used deprecated imp which creates a runtime warning. – sorin May 03 '20 at 10:15
outdated (not longer true)
I believe there is none in the python libraries
>>> def which(pgm):
path=os.getenv('PATH')
for p in path.split(os.path.pathsep):
p=os.path.join(p,pgm)
if os.path.exists(p) and os.access(p,os.X_OK):
return p
>>> os.which=which
>>> os.which('ls.exe')
'C:\\GNUwin32\\bin\\ls.exe'