サーチ…


前書き

ほとんどのコマンドラインツールは、実行時にプログラムに渡される引数に依存しています。入力を促す代わりに、これらのプログラムは、データまたは特定のフラグ(ブール値になる)が設定されることを期待しています。これにより、ユーザーと他のプログラムの両方が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__)


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow