web-dev-qa-db-ja.com

Argparse:引数が渡されたかどうかを確認します

パラメーターが指定されていない場合、スクリプトはデモモードを開始する必要があります。私はこれを試しました:

_args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args
_

argsはリストではないため、*** TypeError: object of type 'Namespace' has no len()を返します。

どうすれば欲しいものを達成できますか?

43
Framester

引数なしがコマンドに与えられたことを検出することが目標である場合、argparseを介してこれを行うのは間違ったアプローチです(Benがうまく指摘しているように)。

シンプルだと思います! :-) argparseは_sys.argv_を減少させないと信じています。したがって、if not len(sys.argv) > 1の場合、ユーザーから引数は提供されていません。

69

argparseを使用すると、仕様と解析するコマンドラインに基づいて、パーサーに追加した引数に記載されているすべての変数を(Namespaceオブジェクト内に)設定できます。デフォルトを設定すると、コマンドラインにこれ​​らの変数が表示されない場合、それらの変数はそのデフォルト値を持ち、Namespaceオブジェクトには存在しません。 do n'tにデフォルトを指定すると、暗黙的なデフォルトのNoneがあります。そのため、Namespaceオブジェクトの長さをチェックしても、どのように処理しても、引数が解析されたかどうかをチェックする方法としては意味がありません。常に同じ長さでなければなりません。

代わりに、デフォルトのない引数がたくさんあることがわかっていて、それらのいずれかがNone以外の値に設定されているかどうかを確認したい場合は、そうします。リスト内包表記とvars関数を使用すると、Martijnの答えに示すように、add_argument呼び出しから名前のリストを複製することなくそれらをループできます。

引数の一部にデフォルト値がある場合、およびコマンドラインで明示的に指定できるデフォルト値がある場合は少し複雑になります(たとえば、0にデフォルト設定される数値引数は、ユーザーにデフォルトを伝えることを不可能にします) 0)を提供します。その場合、引数が何であるかを知らなくても常に機能する一般的な解決策があるかどうかはわかりません。

17
Ben

Argparseを使用しないでください。代わりに、単にsys.argvargparseはネームスペースを作成するため、スクリプトを呼び出したときに使用した引数に応じて、常に値とともに「dict」を提供します。

これは私が過去にやったことです。

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args
7
edelatorre94

(何らかの理由で)引数番号が本当に必要な場合。このコードは非常に役立つことがわかりました(ただし、最適化の程度はわかりません。コメントをいただければ幸いです)。

_args = parser.parse_args()
print( len( vars(args) ) )
_

このバージョンでは、-xxパラメーターのみがカウントされ、追加の値は渡されません。

すべて(も渡される値)が必要な場合は、前述のようにlen(sys.argv)を使用します。

7
2dvisio

完全性のためにYoursを拡張するために次の例を想定します。

_#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __== '__main__':
    main()
_

この例で@Benが言及している名前空間オブジェクトは、argsです。 _parser.add_argument_の文字列から変数が作成されます。 _args.input_または_args.length_または_args.verbose_からアクセスできます。これを確認するには、print(args)を実行します。実際に次のように表示されます。

_Namespace(input=None, length=None, verbose=False)
_

verboseはTrueに設定されているため、存在する場合、inputおよびlengthは単なる変数であり、インスタンス化する必要はありません(引数は提供されません)。

group = parser.add_mutually_exclusive_group()も役立ちます。2つの属性を同時に提供することはできません。

詳細については、以下を参照してください。

3
AdamKalisz

私はそれが古いスレッドであることを知っていますが、他の人にも役立つかもしれないより直接的な解決策を見つけました:

引数が渡されたかどうかを確認できます。

if any(vars(args).values()):
    # evaluate args

または、引数が渡されていない場合(not演算子に注意してください):

if not any(vars(args).values()):
    run_demo()

説明:

  • parse_args()は、すべての引数名とそれに関連する値を含む「Namespace」オブジェクトを返します。例:Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • 引数が渡されていない場合、parse_args()は同じオブジェクトを返しますが、すべての値はNoneとして返されます。例:Namespace(arg1=None, arg2=None)

ただし、このオブジェクトは反復可能ではないため、vars()を使用してdictに変換し、値にアクセスできるようにする必要があります。

最後に、dictが手元にあるので、.values()ですべての値(list内)を取得し、組み込みのany()関数を使用して、値はNoneではありません。わかりやすくするために、any()は、渡されたリストにFalseNone、または0(参照用のドキュメントを確認)でない単一の値がない場合、Falseを返します。

それが役に立てば幸い。

1
Hyuri Pimentel

2dvisioの概念を拡張して、ゼロ以外の引数またはNone引数をカウントしました。

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])
1
gerardw