Check if a program exists from a python script
如何从python脚本检查程序是否存在?
假设您要检查
看到多平台解决方案是最好的,但目前Linux已经足够了。
提示:
-
运行命令并检查返回代码并不总是足够的,因为即使您尝试
--version ,某些工具也会返回非0结果。 - 检查命令时,屏幕上看不到任何内容
此外,我会感谢一个更通用的解决方案,如
shutil.which
让我推荐一个尚未讨论的选项:
1 2 3 4 5 6 7 | 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 |
distutils.spawn.find_executable
已经提到的另一个选项是
Tries to find 'executable' in the directories listed in 'path'
因此,如果您注意,您会注意到该功能的名称有些误导。与
例如,假设您有一个未标记为可执行文件的文件
1 2 3 4 5 6 | def is_tool(name): """Check whether `name` is on PATH.""" from distutils.spawn import find_executable return find_executable(name) is not None |
最简单的方法是尝试使用所需的参数运行程序,并处理异常(如果它不存在):
1 2 3 4 5 6 7 8 | 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 |
这是Python中的常见模式:EAFP
您可以使用对所需二进制文件的子进程调用:
- "哪个":* nix
- "where":Win 2003及更高版本(Xp有一个插件)
获取可执行文件路径(假设它在环境路径中)。
1 2 3 4 5 6 7 8 9 | 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" |
或者只使用Ned Batchelder的wh.py脚本,这是一个"哪个"跨平台实现:
http://nedbatchelder.com/code/utilities/wh_py.html
我会去:
1 2 3 4 | import distutils.spawn def is_tool(name): return distutils.spawn.find_executable(name) is not None |
1 2 3 4 5 6 7 8 9 10 11 | 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 |
我可能会发现
实际上,您需要做的就是检查
1 2 3 4 5 6 7 | import subprocess rc = subprocess.call(['which', 'wget']) if rc == 0: print 'wget installed!' else: print 'wget missing in path!' |
请注意,我在带有cygwin的windows上测试了这个...如果你想弄清楚如何在纯python中实现
更新:在Windows上,您可以使用
我将@ sorin的答案更改如下,原因是它会检查程序的名称而不传递程序的绝对路径
1 2 3 4 5 6 | 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import os import subprocess def is_tool(prog): for dir in os.environ['PATH'].split(os.pathsep): if os.path.exists(os.path.join(dir, prog)): try: subprocess.call([os.path.join(dir, prog)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except OSError, e: return False return True return False |
对@ SvenMarnach代码的略微修改,解决了打印到标准输出流的问题。如果使用
如果要在终端中禁止标准输出流,请不要打印从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import subprocess import os try: stdout_string = subprocess.check_output(["wget","--help"], stderr=subprocess.STDOUT) # print(stdout_string) except subprocess.CalledProcessError as cpe: print(cpe.returncode) print(cpe.output) except OSError as e: if e.errno == os.errno.ENOENT: print(e) else: # Something else went wrong while trying to run `wget` print(e) |
非零退出状态代码和输出字符串在
如果要将可执行文件的标准输出打印到终端,请打印返回的字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import subprocess import os try: stdout_string = subprocess.check_output(["wget","--help"], stderr=subprocess.STDOUT) print(stdout_string) except subprocess.CalledProcessError as cpe: print(cpe.returncode) print(cpe.output) except OSError as e: if e.errno == os.errno.ENOENT: print(e) else: # Something else went wrong while trying to run `wget` print(e) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import subprocess import os import sys try: stdout_string = subprocess.check_output(["bogus"], stderr=subprocess.STDOUT) sys.stdout.write(stdout_string) except subprocess.CalledProcessError as cpe: sys.stderr.write(cpe.returncode) sys.stderr.write(cpe.output) except OSError as e: if e.errno == os.errno.ENOENT: sys.stderr.write(e.strerror) else: # Something else went wrong while trying to run `wget` sys.stderr.write(e.strerror) |