Test if executable exists in Python?

2020-01-23 05:39发布

In Python, is there a portable and simple way to test if an executable program exists?

By simple I mean something like the which command which would be just perfect. I don't want to search PATH manually or something involving trying to execute it with Popen & al and see if it fails (that's what I'm doing now, but imagine it's launchmissiles)

标签: python path
21条回答
劫难
2楼-- · 2020-01-23 05:49

Just remember to specify the file extension on windows. Otherwise, you have to write a much complicated is_exe for windows using PATHEXT environment variable. You may just want to use FindPath.

OTOH, why are you even bothering to search for the executable? The operating system will do it for you as part of popen call & will raise an exception if the executable is not found. All you need to do is catch the correct exception for given OS. Note that on Windows, subprocess.Popen(exe, shell=True) will fail silently if exe is not found.


Incorporating PATHEXT into the above implementation of which (in Jay's answer):

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
查看更多
老娘就宠你
3楼-- · 2020-01-23 05:49

On the basis that it is easier to ask forgiveness than permission I would just try to use it and catch the error (OSError in this case - I checked for file does not exist and file is not executable and they both give OSError).

It helps if the executable has something like a --version flag that is a quick no-op.

import subprocess
myexec = "python2.8"
try:
    subprocess.call([myexec, '--version']
except OSError:
    print "%s not found on path" % myexec

This is not a general solution, but will be the easiest way for a lot of use cases - those where the code needs to look for a single well known executable.

查看更多
▲ chillily
4楼-- · 2020-01-23 05:49

Using the python fabric library:

from fabric.api import *

def test_cli_exists():
    """
    Make sure executable exists on the system path.
    """
    with settings(warn_only=True):
        which = local('which command', capture=True)

    if not which:
        print "command does not exist"

    assert which
查看更多
贪生不怕死
5楼-- · 2020-01-23 05:52

I know this is an ancient question, but you can use distutils.spawn.find_executable. This has been documented since python 2.4 and has existed since python 1.6.

import distutils.spawn
distutils.spawn.find_executable("notepad.exe")

Also, Python 3.3 now offers shutil.which().

查看更多
狗以群分
6楼-- · 2020-01-23 05:52

This seems simple enough and works both in python 2 and 3

try: subprocess.check_output('which executable',shell=True)
except: sys.exit('ERROR: executable not found')
查看更多
干净又极端
7楼-- · 2020-01-23 05:53

None of previous examples do work on all platforms. Usually they fail to work on Windows because you can execute without the file extension and that you can register new extension. For example on Windows if python is well installed it's enough to execute 'file.py' and it will work.

The only valid and portable solution I had was to execute the command and see error code. Any decent executable should have a set of calling parameters that will do nothing.

查看更多
登录 后发表回答