argparse
ソースをいじる以外に、必要なスイッチがないなど、parse_args()
が呼び出されたときに問題が発生した場合に終了ステータスコードを制御する方法はありますか?
引数ごとに終了コードを指定するメカニズムは知りません。 .parse_args()
で発生したSystemExit
例外をキャッチできますが、具体的にを確認する方法がわかりません)がエラーの原因です。
編集:実用的な解決策を探してこれに来る人にとって、以下は状況です:
ArgumentError()
は、引数の解析が失敗したときに適切に発生します。引数インスタンスとメッセージが渡されますArgumentError()
はnot引数をインスタンス属性として格納しますが、渡されます(これは便利です)ArgumentError
をサブクラス化し、.error()をオーバーライドしてsys.exc_info()から例外を取得することにより、ArgumentParser
例外を再発生させることができます。つまり、醜い一方で、次のコードを使用すると、ArgumentError例外をキャッチし、問題の引数とエラーメッセージを取得して、適切と判断できます。
import argparse
import sys
class ArgumentParser(argparse.ArgumentParser):
def _get_action_from_name(self, name):
"""Given a name, get the Action instance registered with this parser.
If only it were made available in the ArgumentError object. It is
passed as it's first arg...
"""
container = self._actions
if name is None:
return None
for action in container:
if '/'.join(action.option_strings) == name:
return action
Elif action.metavar == name:
return action
Elif action.dest == name:
return action
def error(self, message):
exc = sys.exc_info()[1]
if exc:
exc.argument = self._get_action_from_name(exc.argument_name)
raise exc
super(ArgumentParser, self).error(message)
## usage:
parser = ArgumentParser()
parser.add_argument('--foo', type=int)
try:
parser.parse_args(['--foo=d'])
except argparse.ArgumentError, exc:
print exc.message, '\n', exc.argument
有用な方法でテストされていません。通常は、責任を負わないでください。
すべての回答は、argparse実装の詳細をうまく説明しています。
実際、 [〜#〜] pep [〜#〜] で提案されているように(そしてRob Cowieによって指摘されています)、ArgumentParserを継承して動作をオーバーライドする必要がありますerrorまたはexitメソッドの.
私の場合、エラーが発生した場合、使用状況の印刷を完全なヘルプの印刷に置き換えたいだけでした:
class ArgumentParser(argparse.ArgumentParser):
def error(self, message):
self.print_help(sys.stderr)
self.exit(2, '%s: error: %s\n' % (self.prog, message))
オーバーライドの場合、メインコードには最小限の情報が含まれ続けます。
# Parse arguments.
args = parser.parse_args()
# On error this will print help and cause exit with explanation message.
おそらく、SystemExit
例外をキャッチすると、簡単な回避策になります。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
try:
args = parser.parse_args()
except SystemExit:
print("do something else")
インタラクティブなセッションでも、私にとってはうまくいきます。
編集: @Rob Cowieが私をスイッチに倒したようです。彼が言ったように、あなたが愚かになってトレースバックから情報を収集しようとしない限り、これはあまり診断の可能性を持ちません。
既存のメソッドのいずれかを使用できます: http://docs.python.org/library/argparse.html#exiting-methods 。ただし、引数が無効である状況をすでに処理しているはずです(引数が適切に定義されている場合)。
無効な引数を使用:
% [ $(./test_argparse.py> /dev/null 2>&1) ] || { echo error }
error # exited with status code 2
あなたはいじくる必要があります。見る argparse.ArgumentParser.error
、これは内部的に呼び出されるものです。または、引数を非必須にしてから、argparseの外部でチェックして終了することもできます。
Argparse.errorはメソッドであり、クラスではありませんが、「試行」することはできませんが、「認識されない引数」のエラーはすべて「除きます」。そうする場合は、argparseのエラー関数をオーバーライドする必要があります。
def print_help(errmsg):
print(errmsg.split(' ')[0])
parser.error = print_help
args = parser.parse_args()
無効な入力では、次のように出力されます。
unrecognised
アプリケーションの起動時にargparseエラーをキャッチし、そのエラーをwxPythonフォームに渡すための簡単な方法が必要でした。上記の最良の回答を組み合わせると、次の小さな解決策が得られました。
import argparse
# sub class ArgumentParser to catch an error message and prevent application closing
class MyArgumentParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
super(MyArgumentParser, self).__init__(*args, **kwargs)
self.error_message = ''
def error(self, message):
self.error_message = message
def parse_args(self, *args, **kwargs):
# catch SystemExit exception to prevent closing the application
result = None
try:
result = super().parse_args(*args, **kwargs)
except SystemExit:
pass
return result
# testing -------
my_parser = MyArgumentParser()
my_parser.add_argument('arg1')
my_parser.parse_args()
# check for an error
if my_parser.error_message:
print(my_parser.error_message)
それを実行する:
>python test.py
the following arguments are required: arg1