334

Python では、実行可能プログラムが存在するかどうかをテストする移植可能で簡単な方法はありますか?

簡単に言えば、which完璧なコマンドのようなものを意味します。PATH を手動で検索したり、 & al を使用して実行しようとしたり、失敗するかどうかを確認したりしたくありませんPopen(それが私が今行っていることですが、それがlaunchmissiles.

4

15 に答える 15

368

これは昔からの質問ですが、 を使用できますdistutils.spawn.find_executable。これはpython 2.4 から文書化されており、python 1.6 から存在しています。

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

また、Python 3.3 ではshutil.which().

于 2012-09-26T22:40:30.507 に答える
334

私が考えることができる最も簡単な方法:

def which(program):
    import os
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    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)
            if is_exe(exe_file):
                return exe_file

    return None

編集: コード サンプルを更新して、指定された引数が既に実行可能ファイルへのフル パス、つまり "which /bin/ls" であるケースを処理するためのロジックを含めました。これは、UNIX の「which」コマンドの動作を模倣しています。

編集: コメントごとに os.path.exists() の代わりに os.path.isfile() を使用するように更新されました。

編集path.strip('"')ここで行うのは間違っているようです。Windows も POSIX も、引用された PATH 項目を奨励しているようには見えません。

于 2008-12-18T06:05:29.043 に答える
209

Pythonのすばらしい標準ライブラリのshutil.which()を使用してください。電池付属!

于 2012-12-18T16:05:19.767 に答える
20

Windowsでファイル拡張子を指定することを忘れないでください。それ以外の場合は、環境変数is_exeを使用してWindows用に非常に複雑なものを作成する必要があります。FindPathPATHEXTを使用することもできます。

OTOH、なぜ実行可能ファイルを探すのに苦労しているのですか?オペレーティングシステムはpopen呼び出しの一部としてそれを行い、実行可能ファイルが見つからない場合は例外を発生させます。あなたがする必要があるのは、与えられたOSの正しい例外をキャッチすることです。Windowsでは、が見つからないsubprocess.Popen(exe, shell=True)場合はサイレントに失敗することに注意してください。exe


(ジェイの答えで)PATHEXT上記の実装に組み込む:which

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
于 2008-12-18T22:25:15.370 に答える
14

*nix プラットフォーム (Linux および OS X) の場合

これは私のために働いているようです:

Mestreionのおかげで、Linux で動作するように編集されました

def cmd_exists(cmd):
    return subprocess.call("type " + cmd, shell=True, 
        stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0

ここで行っているのは、組み込みコマンドの使用typeと終了コードのチェックです。そのようなコマンドがない場合typeは、1 (またはゼロ以外のステータス コード) で終了します。

stdout と stderr については、typeコマンドの出力を黙らせるだけです。これは、終了ステータス コードにのみ関心があるためです。

使用例:

>>> cmd_exists("jsmin")
True
>>> cmd_exists("cssmin")
False
>>> cmd_exists("ls")
True
>>> cmd_exists("dir")
False
>>> cmd_exists("node")
True
>>> cmd_exists("steam")
False
于 2012-06-17T08:01:46.533 に答える
8

許可よりも許しを求める方が簡単であることに基づいて(そして、重要なことに、コマンドを実行しても安全であるということです)、それを使用してエラーをキャッチしようとします(この場合、OSError-ファイルが存在しないことを確認し、ファイルは実行可能ではなく、どちらも OSError を返します)。

--version実行可能ファイルにor--helpフラグのようなものがある場合に役立ちます。

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

これは一般的な解決策ではありませんが、多くのユース ケース (安全に実行できる、または少なくとも特定のフラグで安全に実行できる既知の単一の実行可能ファイルをコードが探す必要がある場合) にとって最も簡単な方法です。

于 2012-07-26T08:06:30.777 に答える
7

パス名に関するいくつかの便利な関数については、 os.pathモジュールを参照してください。既存のファイルが実行可能かどうかを確認するには、 os.X_OK モードでos.access(path, mode)を使用します。

os.X_OK

パスを実行できるかどうかを判断するために access() のモード パラメータに含める値。

編集:提案された実装には、完全なファイル名を作成するためにwhich()使用する手がかりが1つありません。os.path.join()

于 2008-12-18T06:08:00.147 に答える
2

Windows のサポートを追加

def which(program):
    path_ext = [""];
    ext_list = None

    if sys.platform == "win32":
        ext_list = [ext.lower() for ext in os.environ["PATHEXT"].split(";")]

    def is_exe(fpath):
        exe = os.path.isfile(fpath) and os.access(fpath, os.X_OK)
        # search for executable under windows
        if not exe:
            if ext_list:
                for ext in ext_list:
                    exe_path = "%s%s" % (fpath,ext)
                    if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK):
                        path_ext[0] = ext
                        return True
                return False
        return exe

    fpath, fname = os.path.split(program)

    if fpath:
        if is_exe(program):
            return "%s%s" % (program, path_ext[0])
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            path = path.strip('"')
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return "%s%s" % (exe_file, path_ext[0])
    return None
于 2015-04-17T04:06:02.103 に答える
1

重要な質問は、「実行可能ファイルが存在するかどうかをテストする必要があるのはなぜですか?」です。多分あなたはしませんか?;-)

最近、PNG ファイルのビューアを起動するためにこの機能が必要でした。いくつかの事前定義されたビューアーを繰り返し処理し、存在する最初のものを実行したかったのです。幸いなことに、私は出会いましos.startfileた。それははるかに優れています!シンプルで移植性があり、システムのデフォルトビューアーを使用します。

>>> os.startfile('yourfile.png')

更新:移植性については間違っていましたos.startfile... Windows のみです。Mac では、コマンドを実行する必要がありますopen。そしてxdg_openUnixで。のMac および Unix サポートの追加に関するPython の問題がありos.startfileます。

于 2009-08-25T13:10:52.853 に答える
1

これは十分に単純に見え、Python 2 と 3 の両方で機能します。

try: subprocess.check_output('which executable',shell=True)
except: sys.exit('ERROR: executable not found')
于 2013-10-13T22:43:51.193 に答える
1

「sh」( http://amoffat.github.io/sh/ ) という外部ライブラリを試すことができます。

import sh
print sh.which('ls')  # prints '/bin/ls' depending on your setup
print sh.which('xxx') # prints None
于 2014-11-06T18:05:55.643 に答える
0

したがって、基本的には、マウントされたファイルシステム(必ずしもPATHディレクトリのみである必要はありません)でファイルを検索し、実行可能かどうかを確認する必要があります。これは、次の計画に変換されます。

  • ローカルにマウントされたファイルシステム内のすべてのファイルを列挙します
  • 結果を名前パターンと一致させる
  • 見つかったファイルごとに、実行可能かどうかを確認します

ポータブルな方法でこれを行うには、多くの計算能力と時間が必要になると思います。それは本当にあなたが必要なものですか?

于 2008-12-18T11:34:02.280 に答える
0

標準の Python ディストリビューション (Windows など) にはwhich.py'\PythonXX\Tools\Scripts\which.py'​​ スクリプトがあります。

編集:which.py依存するlsため、クロスプラットフォームではありません。

于 2008-12-19T05:11:05.517 に答える