単純なargparseの例:1つの引数、3つの結果


529

argparse pythonモジュールドキュメントはすばらしいと思いますが、小さな初心者の脳には今すぐ理解するには多すぎます。コマンドラインで数学を実行したり、画面のフォーマット行をいじったり、オプション文字を変更したりする必要はありません。私がやりたいことは、「argがAの場合、これを行い、Bがそれを行う場合、上記のいずれもヘルプを表示せずに終了する場合」です。


15
次にsys.argv、必要な引数を確認します...
JBernardo '15

10
これまでに試しましたか?優れたドキュメントを備えたargparseのラッパーは簡単に使用できます
kirbyfan64sos 2013

157
それはあなたではありません。argparseです。それはあなたを星への旅に連れて行こうとするものであり、あなたがどこに向かっていたかは気にしません。
Florian Heigl 2014

11
クレイジー "pythonic" APIが再び:/
mlvljr

69
どこでも小さな初心者の頭脳のために立ち上がるために、ウィルキーをマットに祝福してください。
ポルカ

回答:


255

元の質問に対する私の理解は2つあります。最初に、可能な最も単純なargparseの例に関して、私はここでそれを見たことがないことに驚いています。もちろん、非常にシンプルになるには、すべてのオーバーヘッドがあり、電力もほとんどありませんが、それで始められるかもしれません。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()

if args.a == 'magic.name':
    print 'You nailed it!'

しかし、この位置引数は今必要です。このプログラムを呼び出すときに省略した場合、引数の不足に関するエラーが発生します。これにより、元の質問の2番目の部分に進みます。Matt Wilkieは、名前付きラベルなしの単一のオプション引数(--optionラベル)を望んでいるようです。上記のコードを次のように変更することをお勧めします。

...
parser.add_argument("a", nargs='?', default="check_string_for_empty")
...
if args.a == 'check_string_for_empty':
    print 'I can tell that no argument was given and I can deal with that here.'
elif args.a == 'magic.name':
    print 'You nailed it!'
else:
    print args.a

よりエレガントな解決策があるかもしれませんが、これは機能し、ミニマリストです。


4
しばらく考えた後、私はこの質問が実際に尋ねられたとおりのQとその時点での苦境に最もよく答えると結論付けます。他の優れた答えは、その価値を証明するのに十分な担当者を獲得し、少しの競争に耐えることができます。:-)
マットウィルキー2014年

@badnack:「a」が表すものは何でもかまいません。たとえばファイル名など、1つの引数が必要な場合は、コマンドラインでファイル名として入力したものです。次に、独自の処理を行って、それがファイルシステムに存在するかどうかを判断することもできますが、それは別のQ&Aです。
マイティパイル2015年

363

これが私がそれを行う方法ですargparse(複数の引数を使用):

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())

args 引数を含む辞書になります:

if args['foo'] == 'Hello':
    # code here

if args['bar'] == 'World':
    # code here

あなたのケースでは、引数を1つだけ追加します。


3
他の答えへの私のコメントで述べたように、argparseの自動ヘルプのフォーマットを維持したいのですが、名前のない引数を持つオプションはないようです(おそらく私はそれを見たときにそれを理解できないだけです) )、たとえば、実行する必要がある、foo.py --action installまたはfoo.py --action remove単に実行する代わりにfoo.py install
マットウィルキー'19

7
@mattwilkie次に、次のように位置引数を定義するparser.add_argument('install', help='Install the app') 必要があります:( 位置引数はで定義できないことに注意してくださいrequired=True
Diego Navarro

32
argparseの初心者として、この回答は、オプションが渡された後のオプションの場所がわからなかったため、本当に役に立ちました。つまり、args上記のようにディクテーションがどのように生成されたかを理解する必要がありました。
mrKelley 2013

3
コマンドラインから直接プログラムを呼び出す場合は「短い形式」を使用し、スクリプト内でプログラム/コマンドを実行する場合は「長い形式」を使用します。その場合、長い形式を使用すると人間が読みやすくなるため、コード/スクリプトのロジックをたどることが容易になります。
ola 14年

17
個人的には、辞書構文としてargs.fooではargs.barなく、引数にアクセスする方がわかりやすいと思います。もちろんどちらの方法でもかまいませんが、argsは実際には辞書ではなくargparse.Namespaceオブジェクトです。
マイケル・ミオール2014

210

argparseドキュメントには、合理的に良いのですが、葉アウト明白ではないかもしれないいくつかの有用な詳細情報。(@Diego Navarroはすでにこれのいくつかについて言及しましたが、私は彼の答えを少し拡張してみます。)基本的な使用法は次のとおりです。

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--my-foo', default='foobar')
parser.add_argument('-b', '--bar-value', default=3.14)
args = parser.parse_args()

元に戻すオブジェクトparse_args()は「名前空間」オブジェクトです。メンバー変数がコマンドライン引数に基づいて名前が付けられているオブジェクトです。Namespaceオブジェクトは、あなたの引数とそれに関連付けられた値にアクセスする方法です。

args = parser.parse_args()
print args.my_foo
print args.bar_value

argparse変数に名前を付けるときに、引数名の「-」がアンダースコアに置き換えられることに注意してください。)

多くの状況では、引数を、値を取らないフラグとして単に使用したい場合があります。これらを次のようにargparseに追加できます。

parser.add_argument('--foo', action='store_true')
parser.add_argument('--no-foo', action='store_false')

上記は、値がTrueの「foo」、値がFalseの「no_foo」という変数をそれぞれ作成します。

if (args.foo):
    print "foo is true"

if (args.no_foo is False):
    print "nofoo is false"

引数を追加するときに「必須」オプションを使用できることにも注意してください。

parser.add_argument('-o', '--output', required=True)

このように、コマンドラインでこの引数を省略した場合、argparse欠落していることが通知され、スクリプトの実行が停止します。

最後に、vars関数を使用して引数のdict構造を作成することが可能であることに注意してください。

args = parser.parse_args()
argsdict = vars(args)
print argsdict['my_foo']
print argsdict['bar_value']

ご覧のとおりvars、引数名をキーとして、その値をer値として、dictを返します。

他にも多くのオプションと実行可能な操作がありますが、これは最も重要で一般的な使用シナリオをカバーするはずです。


3
ポイントは何だ'-f'とは'-b'?なぜこれを省略できないのですか?
user2763361 2014

13
ランタイムオプションごとに「ショートフォーム」(1つのダッシュ)バージョンと「ロングフォーム」(2つのダッシュ)バージョンの両方を持つことはかなり慣例です。これは、たとえば、ほとんどすべての標準的なUnix / Linuxユーティリティで見られます。man cpまたはman lsを実行すると、多くのオプションが両方のフレーバーに含まれていることがわかります(例:)-f, --force。人々がどちらか一方を好む理由は多種多様ですが、どちらの場合でも、プログラムで両方のフォームを使用できるようにするのはかなり標準的です。
DMH 2014

59

Mattはargparseの位置パラメータについて質問しており、Pythonのドキュメントにはこの側面が欠けていることに同意します。位置パラメータの解析と使用の両方を示す〜20の奇数ページには、単一の完全な例はありません。

ここでの他の答えはどれも位置パラメータの完全な例を示していないため、ここに完全な例を示します。

# tested with python 2.7.1
import argparse

parser = argparse.ArgumentParser(description="An argparse example")

parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)')
parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments')

args = parser.parse_args()

if args.action == "install":
    print("You asked for installation")
else:
    print("You asked for something other than installation")

# The following do not work:
# print(args.foo-bar)
# print(args.foo_bar)

# But this works:
print(getattr(args, 'foo-bar'))

私を驚かせたのは、argparseは名前付き引数「--foo-bar」を「foo_bar」に変換しますが、「foo-bar」という名前の位置パラメータは「foo-bar」のままであるため、プログラムで使用してください。

この例の終わり近くにある2行に注目してください。どちらも、foo-bar位置パラメーターの値を取得するようには機能しません。最初のものは明らかに間違っています(算術式args.fooからバーを引いたものです)が、2番目のものも機能しません。

AttributeError: 'Namespace' object has no attribute 'foo_bar'

このfoo-bar属性を使用する場合getattrは、例の最後の行にあるように、を使用する必要があります。クレイジーなのは、を使用dest=foo_barしてプロパティ名をアクセスしやすい名前に変更しようとすると、本当に奇妙なエラーメッセージが表示されるということです。

ValueError: dest supplied twice for positional argument

上記の例の実行方法は次のとおりです。

$ python test.py
usage: test.py [-h] action foo-bar
test.py: error: too few arguments

$ python test.py -h
usage: test.py [-h] action foo-bar

An argparse example

positional arguments:
  action      The action to take (e.g. install, remove, etc.)
  foo-bar     Hyphens are cumbersome in positional arguments

optional arguments:
  -h, --help  show this help message and exit

$ python test.py install foo
You asked for installation
foo


位置foo-barが変換されないという事実foo_barは、bugs.python.org / issue15125で対処されています
hpaulj 2013

2
このバグのより簡単な回避策は、引数「foo-bar」ではなく「foo_bar」を呼び出すだけでprint args.foo_bar機能することです。これは位置引数なので、スクリプトを呼び出すときに名前を指定する必要はないので、ユーザーには関係ありません。
Luator、2015

@luatorそうです、引数の名前を変更するのは簡単ですが、バグレポートの作成者は、不必要な認知的負荷のために、これがまだ機能の誤りであることを立証しています。argparseを使用するときは、一時停止して、オプションと引数のさまざまな命名規則を思い出す必要があります。bugs.python.org/msg164968を参照してください。
Mark E. Haase 2015

1
@mehaase私はこれが修正されるべきである誤った機能であることに完全に同意します。引数の名前を変更することは、使用するよりも簡単で混乱の少ない回避策だと思いますgetattr(値を使用するコードを変更せずに引数をオプションから位置に変更できるため、柔軟性も高くなります)。
Luator、2015

22

この投稿に触発された、さらに別の概要の紹介。

import argparse

# define functions, classes, etc.

# executes when your script is called from the command-line
if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    #
    # define each option with: parser.add_argument
    #
    args = parser.parse_args() # automatically looks at sys.argv
    #
    # access results with: args.argumentName
    #

引数は、次の組み合わせで定義されます。

parser.add_argument( 'name', options... )              # positional argument
parser.add_argument( '-x', options... )                # single-char flag
parser.add_argument( '-x', '--long-name', options... ) # flag with long name

一般的なオプションは次のとおりです。

  • help--help使用時のこの引数の説明。
  • default:引数が省略された場合のデフォルト値。
  • typefloatまたはを期待する場合int(そうでない場合はstr)。
  • dest:フラグに別の名前を付け'-x', '--long-name', dest='longName'ます(例:)。
    注:デフォルトで--long-nameは、args.long_name
  • action:特定の引数を特別に処理するため
    • store_true, store_falseブール引数
      '--foo', action='store_true' => args.foo == True
    • store_constオプションで使用const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count繰り返しオプションの場合、./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append繰り返しオプションの場合、./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • required:フラグが必要な場合、または位置引数が必要でない場合。
  • nargs:N個の引数をキャプチャするフラグ
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • 選択肢:可能な入力を制限します(文字列のリスト、またはの場合は整数として指定type=int

12

Python HOWTOのArgparseチュートリアルに注意してください。これは、次のような最も基本的な例から始まります。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

そして、あまり基本的でないものに進みます。

質問のように、オプションの定義済みの選択肢の例があります。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)

ドキュメントが更新されたことを確認できてうれしいです。OPが5年前に質問を投稿したとき、これは当てはまりませんでした。
ntwrkguru 2016

10

これは主に@DMHのおかげで私の学習プロジェクトで思いついたものです...

デモコード:

import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--flag', action='store_true', default=False)  # can 'store_false' for no-xxx flags
    parser.add_argument('-r', '--reqd', required=True)
    parser.add_argument('-o', '--opt', default='fallback')
    parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more)
    parsed = parser.parse_args()
    # NOTE: args with '-' have it replaced with '_'
    print('Result:',  vars(parsed))
    print('parsed.reqd:', parsed.reqd)

if __name__ == "__main__":
    main()

これは進化した可能性があり、オンラインで利用できます:command-line.py

このコードにワークアウトを与えるスクリプト:command-line-demo.sh


2
最後に、意味のあるargparseの例
opentokix

5

また、plac(ラッパーのラッパーargparse)を使用することもできます。

おまけとして、それはきちんとしたヘルプ指示を生成します-以下を見てください

スクリプトの例:

#!/usr/bin/env python3
def main(
    arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B'])
):
    """General help for application"""
    if arg == 'A':
        print("Argument has value A")
    elif arg == 'B':
        print("Argument has value B")

if __name__ == '__main__':
    import plac
    plac.call(main)

出力例:

引数が指定されていません- example.py

usage: example.py [-h] {A,B}
example.py: error: the following arguments are required: arg

予期しない引数が指定されました- example.py C

usage: example.py [-h] {A,B}
example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B')

正しい引数が指定されました- example.py A

Argument has value A

完全なヘルプメニュー(自動生成)- example.py -h

usage: example.py [-h] {A,B}

General help for application

positional arguments:
  {A,B}       Argument with two possible values

optional arguments:
  -h, --help  show this help message and exit

簡単な説明:

引数の名前は通常、パラメーター名(arg)と同じです。

argパラメーターの後のタプルアノテーションには次の意味があります。

  • 説明(Argument with two possible values
  • 引数のタイプ-'flag'、 'option'、または 'positional'(positional)のいずれか
  • 略語(None
  • 引数値のタイプ-例 float、string(None
  • 制限された選択肢のセット(['A', 'B']

ドキュメンテーション:

placの使用について詳しくは、優れたドキュメントをご覧ください。

Plac:コマンドラインを簡単に解析する


4

他の人が述べたことに追加するには:

私は通常、「dest」パラメーターを使用して変数名を指定し、次に「globals()。update()」を使用してそれらの変数をグローバル名前空間に配置します。

使用法:

$ python script.py -i "Hello, World!"

コード:

...
parser.add_argument('-i', '--input', ..., dest='inputted_variable',...)
globals().update(vars(parser.parse_args()))
...
print(inputted_variable) # Prints "Hello, World!"

内部でおよびをargparse使用getattrsetattrて、名前空間の値にアクセスします。そうすれば、奇妙に形成されたdest値に悩まされることがなくなります。
hpaulj 2013

1

argparseを使用して '-h' / '-help'スイッチを修正し、独自の個人コードのヘルプ手順を表示する本当に簡単な方法は、デフォルトのヘルプをFalseに設定することです。好きなだけ.add_argumentsを追加することもできます。 :

import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('-h', '--help', action='help',
                help='To run this script please provide two arguments')
parser.parse_args()

実行:python test.py -h

出力:

usage: test.py [-h]

optional arguments:
  -h, --help  To run this script please provide two arguments

-1

最も簡単な答え!

PS argparseのドキュメントを書いた人はバカです

Pythonコード:

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('--o_dct_fname',type=str)
parser.add_argument('--tp',type=str)
parser.add_argument('--new_res_set',type=int)
args = parser.parse_args()
o_dct_fname = args.o_dct_fname
tp = args.tp
new_res_set = args.new_res_set

実行中のコード

python produce_result.py --o_dct_fname o_dct --tp father_child --new_res_set 1

この回答は、既存の回答より新しい/異なるものを追加しません。
NVS Abhilash

私は最も
はっきりしていて
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.