Python Language
コマンドライン引数の構文解析
サーチ…
前書き
ほとんどのコマンドラインツールは、実行時にプログラムに渡される引数に依存しています。入力を促す代わりに、これらのプログラムは、データまたは特定のフラグ(ブール値になる)が設定されることを期待しています。これにより、ユーザーと他のプログラムの両方がPythonファイルを実行し、開始時にデータを渡すことができます。この節では、Pythonでのコマンドライン引数の実装と使い方について説明します。
argparseのHello world
次のプログラムは、ユーザーにこんにちはと言います。これは、ユーザーの名前である1つの位置引数をとり、挨拶にも伝えることができます。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('name',
help='name of user'
)
parser.add_argument('-g', '--greeting',
default='Hello',
help='optional alternate greeting'
)
args = parser.parse_args()
print("{greeting}, {name}!".format(
greeting=args.greeting,
name=args.name)
)
$ python hello.py --help
usage: hello.py [-h] [-g GREETING] name
positional arguments:
name name of user
optional arguments:
-h, --help show this help message and exit
-g GREETING, --greeting GREETING
optional alternate greeting
$ python hello.py world
Hello, world!
$ python hello.py John -g Howdy
Howdy, John!
詳細については、 argparseのドキュメントを参照してください。
docoptを使った基本的な例
docoptは、コマンドライン引数の頭を解析します。引数を解析する代わりに、プログラムの使用文字列を書くだけで、docopt は使用文字列を解析し、それを使ってコマンドライン引数を抽出します。
"""
Usage:
script_name.py [-a] [-b] <path>
Options:
-a Print all the things.
-b Get more bees into the path.
"""
from docopt import docopt
if __name__ == "__main__":
args = docopt(__doc__)
import pprint; pprint.pprint(args)
サンプルラン:
$ python script_name.py
Usage:
script_name.py [-a] [-b] <path>
$ python script_name.py something
{'-a': False,
'-b': False,
'<path>': 'something'}
$ python script_name.py something -a
{'-a': True,
'-b': False,
'<path>': 'something'}
$ python script_name.py -b something -a
{'-a': True,
'-b': True,
'<path>': 'something'}
argparseで相互に排他的な引数を設定する
2つ以上の引数を相互に排他的にする場合argparse.ArgumentParser.add_mutually_exclusive_group()
関数を使用することができます。以下の例では、fooまたはbarのいずれかが存在する可能性がありますが、両方同時に存在することはできません。
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-f", "--foo")
group.add_argument("-b", "--bar")
args = parser.parse_args()
print "foo = ", args.foo
print "bar = ", args.bar
--foo
と--bar
引数の両方を指定してスクリプトを実行しようとすると、スクリプトは以下のメッセージを表示します。
error: argument -b/--bar: not allowed with argument -f/--foo
argvでのコマンドライン引数の使用
Pythonスクリプトがコマンドラインから呼び出されるときはいつでも、ユーザは追加のコマンドライン引数をスクリプトに渡すことができます。これらの引数は、システム変数からプログラマに利用できるようになりますsys.argv
(「argvが」ほとんどのプログラミング言語で使用される伝統的な名前であり、そしてそれは、「 引数 umentのVのエクター」を意味します)。
規約では、 sys.argv
リストの最初の要素はPythonスクリプト自体の名前ですが、残りの要素はスクリプトを呼び出すときにユーザーが渡すトークンです。
# cli.py
import sys
print(sys.argv)
$ python cli.py
=> ['cli.py']
$ python cli.py fizz
=> ['cli.py', 'fizz']
$ python cli.py fizz buzz
=> ['cli.py', 'fizz', 'buzz']
argv
の使い方のもう一つの例です。スクリプトの名前が含まれているため、最初にsys.argvの最初の要素を削除します。その後、残りの引数を1つの文にまとめ、最後に、現在ログインしているユーザーの名前の前にその文を印刷します(チャットプログラムをエミュレートするため)。
import getpass
import sys
words = sys.argv[1:]
sentence = " ".join(words)
print("[%s] %s" % (getpass.getuser(), sentence))
多数の非定位置引数を "手動で"解析するときによく使用されるアルゴリズムは、 sys.argv
リストを反復することsys.argv
。 1つの方法は、リストの上に移動して、その各要素をポップすることです。
# reverse and copy sys.argv
argv = reversed(sys.argv)
# extract the first element
arg = argv.pop()
# stop iterating when there's no more args to pop()
while len(argv) > 0:
if arg in ('-f', '--foo'):
print('seen foo!')
elif arg in ('-b', '--bar'):
print('seen bar!')
elif arg in ('-a', '--with-arg'):
arg = arg.pop()
print('seen value: {}'.format(arg))
# get the next value
arg = argv.pop()
argparseを使用したカスタムパーサーエラーメッセージ
スクリプトの必要に応じてパーサーエラーメッセージを作成することができます。これはargparse.ArgumentParser.error
関数によるものです。以下の例は、使用とするエラーメッセージ印刷スクリプト示すstderr
場合--foo
与えられていないが--bar
。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-f", "--foo")
parser.add_argument("-b", "--bar")
args = parser.parse_args()
if args.foo and args.bar is None:
parser.error("--foo requires --bar. You did not specify bar.")
print "foo =", args.foo
print "bar =", args.bar
あなたのスクリプト名がsample.pyと仮定し、実行する: python sample.py --foo ds_in_fridge
スクリプトは以下の文句を言います:
usage: sample.py [-h] [-f FOO] [-b BAR]
sample.py: error: --foo requires --bar. You did not specify bar.
argparse.add_argument_group()による引数の概念的なグループ化
argparse ArgumentParser()を作成し、 '-h'を指定してプログラムを実行すると、ソフトウェアを実行できる引数を説明する自動使用メッセージが表示されます。デフォルトでは、位置引数と条件引数は2つのカテゴリに分かれています。たとえば、小さなスクリプト(example.py)とpython example.py -h
を実行したときの出力があります。
import argparse
parser = argparse.ArgumentParser(description='Simple example')
parser.add_argument('name', help='Who to greet', default='World')
parser.add_argument('--bar_this')
parser.add_argument('--bar_that')
parser.add_argument('--foo_this')
parser.add_argument('--foo_that')
args = parser.parse_args()
usage: example.py [-h] [--bar_this BAR_THIS] [--bar_that BAR_THAT]
[--foo_this FOO_THIS] [--foo_that FOO_THAT]
name
Simple example
positional arguments:
name Who to greet
optional arguments:
-h, --help show this help message and exit
--bar_this BAR_THIS
--bar_that BAR_THAT
--foo_this FOO_THIS
--foo_that FOO_THAT
ユーザーを助けるために引数をさらに概念的なセクションに分けたい場合もあります。たとえば、すべての入力オプションを1つのグループに、すべての出力形式オプションを別のグループに含めることができます。上記の例では、分離するように調整することができる--foo_*
の引数--bar_*
ようなので引数を。
import argparse
parser = argparse.ArgumentParser(description='Simple example')
parser.add_argument('name', help='Who to greet', default='World')
# Create two argument groups
foo_group = parser.add_argument_group(title='Foo options')
bar_group = parser.add_argument_group(title='Bar options')
# Add arguments to those groups
foo_group.add_argument('--bar_this')
foo_group.add_argument('--bar_that')
bar_group.add_argument('--foo_this')
bar_group.add_argument('--foo_that')
args = parser.parse_args()
python example.py -h
を実行すると、この出力が生成されます:
usage: example.py [-h] [--bar_this BAR_THIS] [--bar_that BAR_THAT]
[--foo_this FOO_THIS] [--foo_that FOO_THAT]
name
Simple example
positional arguments:
name Who to greet
optional arguments:
-h, --help show this help message and exit
Foo options:
--bar_this BAR_THIS
--bar_that BAR_THAT
Bar options:
--foo_this FOO_THIS
--foo_that FOO_THAT
docoptとdocopt_dispatchによる高度な例
docoptと同様に、[docopt_dispatch]を使うと、エントリポイントモジュールの__doc__
変数に--help
を作ることができます。そこでは、引数としてdoc文字列を指定してdispatch
を呼び出すので、その上でパーサーを実行できます。
そうすることで、手動で引数を処理する代わりに(通常は高いサイクロマティックなif / else構造で終わる)、ディスパッチされたままにして、引数のセットをどのように処理するかだけを指定します。
これはdispatch.on
デコレータの目的です:関数をトリガすべき引数または引数のシーケンスを与え、その関数はパラメータとして一致する値とともに実行されます。
"""Run something in development or production mode.
Usage: run.py --development <host> <port>
run.py --production <host> <port>
run.py items add <item>
run.py items delete <item>
"""
from docopt_dispatch import dispatch
@dispatch.on('--development')
def development(host, port, **kwargs):
print('in *development* mode')
@dispatch.on('--production')
def development(host, port, **kwargs):
print('in *production* mode')
@dispatch.on('items', 'add')
def items_add(item, **kwargs):
print('adding item...')
@dispatch.on('items', 'delete')
def items_delete(item, **kwargs):
print('deleting item...')
if __name__ == '__main__':
dispatch(__doc__)