subprocess
OSError
コマンドが見つからない場合、例外が発生します。
コマンドが検出され、コマンドがsubprocess
実行されると、コマンドから結果コードが返されます。標準では、コード 0 は成功を意味し、失敗はゼロ以外のエラー コードです (これはさまざまです。実行している特定のコマンドのドキュメントを確認してください)。
なので、キャッチすればOSError
存在しないコマンドを扱えるし、リザルトコードを見ればコマンドが成功したかどうかがわかります。
の優れた点は、とsubprocess
からすべてのテキストを収集できることです。その後、好きなように、それを破棄したり、返したり、ログに記録したり、表示したりできます。コマンドが失敗してテキストが出力されない限り、コマンドからのすべての出力を破棄するラッパーをよく使用します。stdout
stderr
stderr
ユーザーに実行可能ファイルをコピーするように頼むべきではないことに同意します。PATH
プログラムは、変数にリストされたディレクトリにある必要があります。プログラムが見つからない場合はインストールする必要があります。または、ユーザー以外のディレクトリにインストールされている場合は、そのディレクトリを含めるように をPATH
更新する必要があります。PATH
subprocess
実行可能ファイルへのさまざまなハードコードされたパスを使用して、複数回試行するオプションがあることに注意してください。
import os
import subprocess as sp
def _run_cmd(s_cmd, tup_args):
lst_cmd = [s_cmd]
lst_cmd.extend(tup_args)
result = sp.call(lst_cmd)
return result
def run_lumberjack(*tup_args):
try:
# try to run from /usr/local/bin
return _run_cmd("/usr/local/bin/lumberjack", tup_args)
except OSError:
pass
try:
# try to run from /opt/forest/bin
return _run_cmd("/opt/forest/bin/lumberjack", tup_args)
except OSError:
pass
try:
# try to run from "bin" directory in user's home directory
home = os.getenv("HOME", ".")
s_cmd = home + "/bin/lumberjack"
return _run_cmd(s_cmd, tup_args)
except OSError:
pass
# Python 3.x syntax for raising an exception
# for Python 2.x, use: raise OSError, "could not find lumberjack in the standard places"
raise OSError("could not find lumberjack in the standard places")
run_lumberjack("-j")
編集:少し考えた後、上記を完全に書き直すことにしました。場所のリストを渡すだけで、ループが機能するまで別の場所を試す方がはるかにクリーンです。しかし、必要がなければユーザーのホーム ディレクトリの文字列を作成したくなかったので、callable を代替のリストに入れることを正当化しました。これについて質問がある場合は、質問してください。
import os
import subprocess as sp
def try_alternatives(cmd, locations, args):
"""
Try to run a command that might be in any one of multiple locations.
Takes a single string argument for the command to run, a sequence
of locations, and a sequence of arguments to the command. Tries
to run the command in each location, in order, until the command
is found (does not raise OSError on the attempt).
"""
# build a list to pass to subprocess
lst_cmd = [None] # dummy arg to reserve position 0 in the list
lst_cmd.extend(args) # arguments come after position 0
for path in locations:
# It's legal to put a callable in the list of locations.
# When this happens, we should call it and use its return
# value for the path. It should always return a string.
if callable(path):
path = path()
# put full pathname of cmd into position 0 of list
lst_cmd[0] = os.path.join(path, cmd)
try:
return sp.call(lst_cmd)
except OSError:
pass
raise OSError('command "{}" not found in locations list'.format(cmd))
def _home_bin():
home = os.getenv("HOME", ".")
return os.path.join(home, "bin")
def run_lumberjack(*args):
locations = [
"/usr/local/bin",
"/opt/forest/bin",
_home_bin, # specify callable that returns user's home directory
]
return try_alternatives("lumberjack", locations, args)
run_lumberjack("-j")