39

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

Joe
  • 16,328
  • 12
  • 61
  • 75

3 Answers3

85

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.

joemaller
  • 19,579
  • 7
  • 67
  • 84
15

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'
Six
  • 5,122
  • 3
  • 29
  • 38
10

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'
sorin
  • 161,544
  • 178
  • 535
  • 806
Abhijit
  • 62,056
  • 18
  • 131
  • 204