実行可能ファイルのパスを見つけるにはどうすればよいですか?


84

バイナリへのパスを使用して環境をセットアップする必要があります。シェルではwhich、パスを見つけるために使用できます。Pythonに同等のものはありますか?これは私のコードです。

cmd = ["which","abc"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
res = p.stdout.readlines()
if len(res) == 0: return False
return True

シェル自体でwhichも、コマンドがインストールされているかどうかを検出するのに適していません。参考
小次郎2015

回答:


94

6
+1、これはクールで標準ライブラリの一部です!Windowsでは非常に制限されていることに注意してください-PATHEXTを解析せず、代わりに「.exe」拡張子を検索する必要があると想定します(バッチファイルがないなど)
orip

2
ファイルが実行可能かどうかはチェックされないことに注意してください。
temoto 2016年

1
これは2.7または3.6では機能しませんでした。スポーンモジュールが見つからないというエラーが発生しました。
GreenMatt

@temotoそれでも、Windows上で私用のdllファイル(確認できるのはPATH経由where.exe)が見つかりません。
jpmc 2619

@GreenMattは、3.7で試してみましたが、問題なく動作します。他の人が言ったように、import distutils.spawn最初に実行することを忘れないでください。
zonksoft

82

これは古い質問ですが、Python 3.3以降を使用してshutil.which(cmd)いる場合は、を使用できます。ドキュメントはここにあります。標準ライブラリにあるという利点があります。

例は次のようになります。

>>> import shutil
>>> shutil.which("bash")
'/usr/bin/bash'

13

これを行うコマンドはありませんが、繰り返しenviron["PATH"]てファイルが存在するかどうかを確認whichできます。これが実際に行われていることです。

import os

def which(file):
    for path in os.environ["PATH"].split(os.pathsep):
        if os.path.exists(os.path.join(path, file)):
                return os.path.join(path, file)

    return None

幸運を!


1
あなたはpathsepキャラクターについての仮定を慎重にしたいと思っています。
ジョンパーシバルハックワース2011年

とパス区切り文字ですが、これはポイントを作るための単なる癖です。幸運を!
ゴンザロララルデ2011年

os.path.sep代わりに/、のos.pathsep代わりに使用:
djhaskin987 2014

2
'+'は使用せず、os.path.joinを使用してください。stdlib実装(distutils)の賛成票を増やし、Twistedプロジェクトからプラットフォームに依存しないようにします。
2015

os.path.joinに感謝します。ねじれた実装は完全に分離されており、プロジェクトの他の部分との相互依存性はないようです。そのため、実装としては(少なくとも私のものよりも)はるかに優れています
Gonzalo Larralde 2015

13

同様の質問

Twistedの実装を参照してください:twisted.python.procutils.which


それには、Twistedモジュールをインストールする必要があります。これは、Windowsで(Christoph Gohlkeのホイールを使用しても)痛みを伴う可能性があります。
Agi Hammerthief 2016

1
Twisted実装へのリンクが壊れています。それのように見えますが、ここで見つけることができます:github.com/twisted/twisted/blob/trunk/src/twisted/python/...
rkersh

4

次のようなことを試すことができます。

import os
import os.path
def which(filename):
    """docstring for which"""
    locations = os.environ.get("PATH").split(os.pathsep)
    candidates = []
    for location in locations:
        candidate = os.path.join(location, filename)
        if os.path.isfile(candidate):
            candidates.append(candidate)
    return candidates

あなたPATHEXTも考慮に入れる必要があります
orip 2011年

2
Windowsマシンでは、拡張子を想定するのではなく、ファイルの正確な名前を探す可能性が高いと思います。そうは言っても、PATHEXTのメンバーを反復処理する内部ループを追加するのは難しくありません。
ジョンパーシバルハックワース2011年

3

を使用するとshell=True、コマンドはシステムシェルを介して実行され、パス上のバイナリが自動的に検出されます。

p = subprocess.Popen("abc", stdout=subprocess.PIPE, shell=True)

それがなくshell=Trueてもパスで検索されますが、可能なコマンドのどれが存在するかを見つけたい場合は役に立ちません。
アンティハーパラ2015年

3

これは、ファイルが存在するかどうかだけでなく、実行可能かどうかもチェックするwhichコマンドと同等です。

import os

def which(file_name):
    for path in os.environ["PATH"].split(os.pathsep):
        full_path = os.path.join(path, file_name)
        if os.path.exists(full_path) and os.access(full_path, os.X_OK):
            return full_path
    return None

0

これは、以前の回答の1行バージョンです。

import os
which = lambda y: next(filter(lambda x: os.path.isfile(x) and os.access(x,os.X_OK),[x+os.path.sep+y for x in os.getenv("PATH").split(os.pathsep)]),None)

そのように使用されます:

>>> which("ls")
'/bin/ls'

これはPython2では機能しないようですTypeError: list object is not an iterator
gibbsoft 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.