检查python脚本中是否存在程序

sor*_*rin 49 python

如何从python脚本检查程序是否存在?

比方说,你要检查wgetcurl可用.我们假设他们应该走在路上.

看到多平台解决方案是最好的,但目前Linux已经足够了.

提示:

  • 运行命令并检查返回代码并不总是足够的,因为即使您尝试,某些工具也会返回非0结果--version.
  • 检查命令时,屏幕上看不到任何内容

此外,我会感谢一个更通用的解决方案,比如 is_tool(name)

Six*_*Six 80

shutil.which

让我推荐一个尚未讨论的选项:which具体的Python实现shutil.which.它是在Python 3.3中引入的,是跨平台的,支持Linux,Mac和Windows.它也可以在Python 2.x中通过whichcraft获得.您也可以直接将代码which这里删除,并将其插入您的程序中.

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
Run Code Online (Sandbox Code Playgroud)

distutils.spawn.find_executable

已经提到的另一个选择是distutils.spawn.find_executable.

find_executable的文档如下:

试图在'path'中列出的目录中找到'可执行文件'

因此,如果您注意,您会注意到该功能的名称有些误导.不同which,find_executable实际上并没有验证executable是否标记为可执行文件,只是它在PATH上.因此,完全可能(但不太可能)find_executable表示程序可用时不可用.

例如,假设您有一个/usr/bin/wget未标记为可执行文件的文件.wget从shell 运行将导致以下错误:bash:/ usr/bin/wget:权限被拒绝.which('wget') is not None将返回False,但find_executable('wget') is not None将返回True.您可以使用任何一种功能,但这只是需要注意的事情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
Run Code Online (Sandbox Code Playgroud)

  • `shutil.which()` 的文档链接:https://docs.python.org/3/library/shutil.html#shutil.which (4认同)

Sve*_*ach 40

最简单的方法是尝试使用所需的参数运行程序,并处理异常(如果它不存在):

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
Run Code Online (Sandbox Code Playgroud)

这是Python中的常见模式:EAFP


J_Z*_*Zar 14

您可以使用对所需二进制文件的子进程调用:

  • "哪个":*nix
  • "where":Win 2003及更高版本(Xp有一个插件)

获取可执行文件路径(假设它在环境路径中).

import os 
import platform
import subprocess

cmd = "where" if platform.system() == "Windows" else "which"
try: 
    subprocess.call([cmd, your_executable_to_check_here])
except: 
    print "No executable"
Run Code Online (Sandbox Code Playgroud)

或者只使用Ned Batchelder的wh.py脚本,这是一个"哪个"跨平台实现:

http://nedbatchelder.com/code/utilities/wh_py.html


Mar*_*ard 11

我会去:

import distutils.spawn

def is_tool(name):
  return distutils.spawn.find_executable(name) is not None
Run Code Online (Sandbox Code Playgroud)


sor*_*rin 10

import subprocess
import os

def is_tool(name):
    try:
        devnull = open(os.devnull)
        subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate()
    except OSError as e:
        if e.errno == os.errno.ENOENT:
            return False
    return True
Run Code Online (Sandbox Code Playgroud)

  • 对于使用Python 3.3及更高版本的人来说,也可以使用`subprocess.DEVNULL`而不是`open(os.devnull)`. (3认同)
  • 如果它填充stdout或stderr的管道缓冲区,这将使子进程无限期地运行.如果你想完全运行**只是为了检查它是否存在,你应该使用open`os.devnull`并将其用作stdout和stderr. (2认同)

Dar*_*mas 6

我可能会发出which wget或者which curl检查结果是否以您正在使用的程序的名称结束.unix的魔力:)

实际上,您需要做的就是检查返回代码which.所以...使用我们可靠的subprocess模块:

import subprocess

rc = subprocess.call(['which', 'wget'])
if rc == 0:
    print 'wget installed!'
else:
    print 'wget missing in path!'
Run Code Online (Sandbox Code Playgroud)

请注意,我在带有cygwin的Windows上测试了这个...如果你想弄清楚如何which在纯python中实现,我建议你在这里查看:http://pypi.python.org/pypi/pycoreutils(哦亲爱的 - 看起来似乎他们不供应which.友好推动的时间?)

更新:在Windows上,您可以使用where而不是which类似的效果.


Nic*_*nie 5

我将@sorin的答案更改如下,原因是它会检查程序的名称而不传递程序的绝对路径

from subprocess import Popen, PIPE

def check_program_exists(name):
    p = Popen(['/usr/bin/which', name], stdout=PIPE, stderr=PIPE)
    p.communicate()
    return p.returncode == 0
Run Code Online (Sandbox Code Playgroud)

  • 遗憾的是,此解决方案不适用于 Windows 平台 (2认同)