Python では、実行可能プログラムが存在するかどうかをテストする移植可能で簡単な方法はありますか?
簡単に言えば、which
完璧なコマンドのようなものを意味します。PATH を手動で検索したり、 & al を使用して実行しようとしたり、失敗するかどうかを確認したりしたくありませんPopen
(それが私が今行っていることですが、それがlaunchmissiles
.
これは昔からの質問ですが、 を使用できますdistutils.spawn.find_executable
。これはpython 2.4 から文書化されており、python 1.6 から存在しています。
import distutils.spawn
distutils.spawn.find_executable("notepad.exe")
また、Python 3.3 ではshutil.which()
.
私が考えることができる最も簡単な方法:
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 項目を奨励しているようには見えません。
Pythonのすばらしい標準ライブラリのshutil.which()を使用してください。電池付属!
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
これは私のために働いているようです:
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
許可よりも許しを求める方が簡単であることに基づいて(そして、重要なことに、コマンドを実行しても安全であるということです)、それを使用してエラーをキャッチしようとします(この場合、OSError-ファイルが存在しないことを確認し、ファイルは実行可能ではなく、どちらも OSError を返します)。
--version
実行可能ファイルにor--help
フラグのようなものがある場合に役立ちます。
import subprocess
myexec = "python2.8"
try:
subprocess.call([myexec, '--version']
except OSError:
print "%s not found on path" % myexec
これは一般的な解決策ではありませんが、多くのユース ケース (安全に実行できる、または少なくとも特定のフラグで安全に実行できる既知の単一の実行可能ファイルをコードが探す必要がある場合) にとって最も簡単な方法です。
パス名に関するいくつかの便利な関数については、 os.pathモジュールを参照してください。既存のファイルが実行可能かどうかを確認するには、 os.X_OK モードでos.access(path, mode)を使用します。
os.X_OK
パスを実行できるかどうかを判断するために access() のモード パラメータに含める値。
編集:提案された実装には、完全なファイル名を作成するためにwhich()
使用する手がかりが1つありません。os.path.join()
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
重要な質問は、「実行可能ファイルが存在するかどうかをテストする必要があるのはなぜですか?」です。多分あなたはしませんか?;-)
最近、PNG ファイルのビューアを起動するためにこの機能が必要でした。いくつかの事前定義されたビューアーを繰り返し処理し、存在する最初のものを実行したかったのです。幸いなことに、私は出会いましos.startfile
た。それははるかに優れています!シンプルで移植性があり、システムのデフォルトビューアーを使用します。
>>> os.startfile('yourfile.png')
更新:移植性については間違っていましたos.startfile
... Windows のみです。Mac では、コマンドを実行する必要がありますopen
。そしてxdg_open
Unixで。のMac および Unix サポートの追加に関するPython の問題がありos.startfile
ます。
これは十分に単純に見え、Python 2 と 3 の両方で機能します。
try: subprocess.check_output('which executable',shell=True)
except: sys.exit('ERROR: executable not found')
「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
したがって、基本的には、マウントされたファイルシステム(必ずしもPATHディレクトリのみである必要はありません)でファイルを検索し、実行可能かどうかを確認する必要があります。これは、次の計画に変換されます。
ポータブルな方法でこれを行うには、多くの計算能力と時間が必要になると思います。それは本当にあなたが必要なものですか?
標準の Python ディストリビューション (Windows など) にはwhich.py'\PythonXX\Tools\Scripts\which.py'
スクリプトがあります。
編集:which.py
依存するls
ため、クロスプラットフォームではありません。