54

ソースをいじる以外に、必要なスイッチがないなど、呼び出されargparseたときに問題が発生した場合に、終了ステータス コードを制御する方法はありますか?parse_args()

4

8 に答える 8

56

引数ごとに終了コードを指定するメカニズムを知りません。SystemExit発生した例外をキャッチできますが、エラーの具体的な原因を特定.parse_args()する方法がわかりません。

編集:実用的な解決策を探してこれに来る人にとって、次のような状況があります:

  • ArgumentError()引数の解析が失敗したときに適切に発生します。引数インスタンスとメッセージが渡されます
  • ArgumentError()渡されたにもかかわらず、引数をインスタンス属性として保存しません(これは便利です)
  • ArgumentError.error() をサブクラス化ArgumentParserし、オーバーライドし、sys.exc_info() から例外を取得することで、例外を再発生させることができます。

つまり、次のコードは (見苦しいですが)、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

有用な方法でテストされていません。通常の「壊れたら責めないで」の補償が適用されます。

于 2011-05-09T22:49:58.660 に答える
50

すべての回答は、argparse実装の詳細をうまく説明しています。

実際、PEPで提案されている(そして Rob Cowie によって指摘されている)ように、 ArgumentParserを継承し、エラーまたは終了メソッドの動作をオーバーライドする必要があります。

私の場合、エラーが発生した場合に使用状況の印刷を完全なヘルプの印刷に置き換えたかっただけです。

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.
于 2013-06-05T14:08:50.220 に答える
40

おそらく、SystemExit例外をキャッチすることは簡単な回避策になるでしょう:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
try:
    args = parser.parse_args()
except SystemExit:
    print("do something else")

インタラクティブなセッションでも機能します。

編集: @Rob Cowieが私をスイッチに打ち負かしたようです。彼が言ったように、愚かになってトレースバックから情報を収集しようとしない限り、これには診断の可能性はあまりありません。

于 2011-05-09T22:50:38.557 に答える
15

Python 3.9 の時点で、これはそれほど苦痛ではなくなりました。これは、新しいargparse.ArgumentParser exit_on_errorインスタンス化引数を介して処理できるようになりました。以下に例を示します (python ドキュメントから少し変更: argparse#exit_on_error ):

parser = argparse.ArgumentParser(exit_on_error=False)
parser.add_argument('--integers', type=int)

try:
    parser.parse_args('--integers a'.split())
except argparse.ArgumentError:
    print('Catching an argumentError')
    exit(-1)
于 2021-01-20T19:02:01.650 に答える
2

既存のメソッドの 1 つを使用できます: http://docs.python.org/library/argparse.html#exiting-methods。ただし、引数が無効な状況は既に処理されているはずです (引数を適切に定義していると仮定します)。

無効な引数の使用:

% [ $(./test_argparse.py> /dev/null 2>&1) ] || { echo error } 
error # exited with status code 2
于 2011-05-09T22:41:13.917 に答える
2

いじくり回す必要があります。argparse.ArgumentParser.error内部で呼び出される を見てください。または、引数を非必須にしてから、argparse の外でチェックして終了することもできます。

于 2011-05-09T22:41:37.053 に答える