web-dev-qa-db-ja.com

Python、argparse:type = strおよびtype = intでnargs = 2を使用する方法

私はargparseのドキュメントに何回か費やしましたが、プログラムの1つのオプションについて、このモジュールにまだ苦労しています。

parser.add_argument("-r", "--rmsd", dest="rmsd", nargs=2,
    help="extract the poses that are close from a ref according RMSD",
    metavar=("ref","rmsd"))

最初の引数を文字列(タイプstr)にして必須にしたいのですが、2番目の引数はタイプintにして、値が指定されていない場合はデフォルトの値にしてください(いう default=50)。期待される引数が1つだけの場合にその方法を知っていますが、nargs = 2の場合の処理​​方法がわかりません...それは可能ですか?

18
Bux31

次のことができます。 requiredキーワードは、フィールドを必須に設定し、default=50指定しない場合、オプションのデフォルト値を50に設定します。

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("-s", "--string", type=str, required=True)
parser.add_argument("-i", "--integer", type=int, default=50)

args = parser.parse_args()    
print args.string
print args.integer

出力:

$ python arg_parser.py -s test_string
    test_string
    50
$ python arg_parser.py -s test_string -i 100
    test_string
    100
$ python arg_parser.py -i 100
    usage: arg_parser.py [-h] -s STRING [-i INTEGER]
    arg_parser.py: error: argument -s/--string is required
14
ashokadhikari

私はマイクの解決策に同意する傾向がありますが、これは別の方法です。 usage/help文字列はユーザ​​ーに1つ以上の引数を使用するように指示するため、これは理想的ではありません。

import argparse

def string_integer(int_default):
    """Action for argparse that allows a mandatory and optional
    argument, a string and integer, with a default for the integer.

    This factory function returns an Action subclass that is
    configured with the integer default.
    """
    class StringInteger(argparse.Action):
        """Action to assign a string and optional integer"""
        def __call__(self, parser, namespace, values, option_string=None):
            message = ''
            if len(values) not in [1, 2]:
                message = 'argument "{}" requires 1 or 2 arguments'.format(
                    self.dest)
            if len(values) == 2:
                try:
                    values[1] = int(values[1])
                except ValueError:
                    message = ('second argument to "{}" requires '
                               'an integer'.format(self.dest))
            else:
                values.append(int_default)
            if message:
                raise argparse.ArgumentError(self, message)            
            setattr(namespace, self.dest, values)
    return StringInteger

それで、あなたは得ます:

>>> import argparse
>>> parser = argparse.ArgumentParser(description="")
parser.add_argument('-r', '--rmsd', dest='rmsd', nargs='+',
...                         action=string_integer(50),
...                         help="extract the poses that are close from a ref "
...                         "according RMSD")
>>> parser.parse_args('-r reference'.split())
Namespace(rmsd=['reference', 50])
>>> parser.parse_args('-r reference 30'.split())
Namespace(rmsd=['reference', 30])
>>> parser.parse_args('-r reference 30 3'.split())
usage: [-h] [-r RMSD [RMSD ...]]
: error: argument -r/--rmsd: argument "rmsd" requires 1 or 2 arguments
>>> parser.parse_args('-r reference 30.3'.split())
usage: [-h] [-r RMSD [RMSD ...]]
: error: argument -r/--rmsd: second argument to "rmsd" requires an integer
9
user707650

ジャンプが遅くなってすみません。タイプを呼び出す関数を使用します。

def two_args_str_int(x):
    try:
        return int(x)
    except:
        return x

parser.add_argument("-r", "--rmsd", dest="rmsd", nargs=2, type=two_args_str_int
    help="extract the poses that are close from a ref according RMSD",
    metavar=("ref","rmsd"))
1
Grant Mills

2つの引数を使用することをお勧めします。

import argparse

parser = argparse.ArgumentParser(description='Example with to arguments.')

parser.add_argument('-r', '--ref', dest='reference', required=True,
                    help='be helpful')
parser.add_argument('-m', '--rmsd', type=int, dest='reference_msd',
                    default=50, help='be helpful')

args = parser.parse_args()
print args.reference
print args.reference_msd
1
Mike Müller

私は同様の問題を抱えていましたが、ペアのリストが必要なため、「2つの引数を使用する」アプローチは機能しませんでした。parser.add_argument('--replace', nargs=2, action='append')と個別の引数を使用する場合、リストの長さなどを検証する必要があります。これが私がしたことです:

  1. ヘルプを適切に表示するには、Tuplemetavarに使用します。Tuple=('OLD', 'NEW')の結果、ヘルプ文字列は--replace OLD NEWとして表示されます。文書化されていますが、別のオプションを試すまでは見つかりませんでした。
  2. カスタム検証を使用します。parse_argsの後に、結果のリストのアイテムを検証し、何か問題がある場合はparser.error()を呼び出します。これは、データ型が異なるためです。
0
MarSoft