91

Pythonスクリプトからプログラムが存在するかどうかを確認するにはどうすればよいですか?

wgetまたはが利用可能かどうかを確認したいとしcurlます。それらがパス内にあると仮定します。

マルチプラットフォーム ソリューションを見るのが最善ですが、現時点では Linux で十分です。

ヒント:

  • コマンドを実行して戻りコードを確認するだけでは、必ずしも十分とは言えません--version
  • コマンドをチェックするときに、画面に何も表示されないようにする必要があります

また、次のようなより一般的な解決策をいただければ幸いですis_tool(name)

4

9 に答える 9

177

shutil.which

まだ議論されていないオプションをお勧めします: の Python 実装which、具体的にはshutil.which. Python 3.3 で導入され、Linux、Mac、および Windows をサポートするクロスプラットフォームです。whichcraftを介して Python 2.x でも利用できます。ここwhichで whichcraftのコードをそのまま切り取って、プログラムに挿入することもできます。

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

すでに言及されている別のオプションはdistutils.spawn.find_executable.

find_executableのドキュメント文字列は次のとおりです。

「パス」にリストされたディレクトリで「実行可能ファイル」を見つけようとします

したがって、注意を払うと、関数の名前がやや誤解を招くことに気付くでしょう。とは異なりwhichfind_executableが実行可能としてマークされていることを実際に確認するのではなくexecutable、PATH 上にあることのみを確認します。find_executableしたがって、プログラムが利用可能でないときに利用可能であることを示すことは完全に可能です (ただし、可能性は低いです) 。

たとえば、/usr/bin/wget実行可能としてマークされていないファイルがあるとします。wgetシェルから実行すると、次のエラーが発生します: bash: /usr/bin/wget: Permission deniedwhich('wget') is not NoneFalsefind_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
于 2015-12-09T11:12:00.720 に答える
50

最も簡単な方法は、目的のパラメーターを使用してプログラムを実行し、存在しない場合は例外を処理することです。

try:
    subprocess.call(["wget", "your", "parameters", "here"])
except FileNotFoundError:
    # handle file not found error.

これは Python の一般的なパターンです: EAFP

OsErrorPython 2では、OS エラー用のよりきめ細かい例外クラスがまだ存在していなかったため、代わりに catch を実行する必要がありました。

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
于 2012-06-26T14:59:03.573 に答える
15

で必要なバイナリへのサブプロセス呼び出しを使用できます。

  • "どの" : *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"

または、Ned Batchelder の w.py スクリプトを使用するだけです。これは、「どの」クロスプラットフォーム実装です。

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

于 2012-06-26T15:05:59.077 に答える
13
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
于 2012-06-26T15:37:24.693 に答える
12

私は行きます:

import distutils.spawn

def is_tool(name):
  return distutils.spawn.find_executable(name) is not None
于 2015-04-09T12:32:10.697 に答える
11

おそらくwhich wgetorにシェルアウトしwhich curlて、結果が使用しているプログラムの名前で終わることを確認します。Unixの魔法:)

実際には、 のリターン コードを確認するだけで済みますwhich。だから...私たちの信頼できるsubprocessモジュールを使用して:

import subprocess

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

whichcygwin を使用して Windows でこれをテストしたことに注意してください...純粋な python で実装する方法を理解したい場合は、ここを確認することをお勧めします: http://pypi.python.org/pypi/pycoreutils (ああ、どうやら彼らは供給しませんwhich.友好的なナッジの時間ですか?)

更新: Windows では、where代わりにwhich同様の効果を得るために使用できます。

于 2012-06-26T14:58:12.573 に答える
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
于 2016-09-11T20:29:39.637 に答える
1
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
于 2012-06-26T14:59:59.120 に答える