optparse – getopt に代わるコマンドラインオプションパーサ

目的:getopt に代わるコマンドラインオプションパーサ
利用できるバージョン:2.3

optparse モジュールはコマンドラインオプションを解析するためのモダンな代替方法で、データ型の変換、オプション処理のコールバック、自動ヘルプ生成といった getopt にはない機能を提供します。ここで説明する内容よりも optparse にはもっと多くの機能があります。とはいえ、本稿ではより汎用的な機能の使用方法を紹介します。

OptionParser を作成する

optparse を使用してオプションを解析するには2つの段階があります。先ずは OptionParser インスタンスを構築して、使用するオプションを設定します。次にオプションが渡されて処理されます。

import optparse
parser = optparse.OptionParser()

通常 parser は1度だけ作成されます。そのオプションがコマンドラインで現れたときにどう処理するかに関しての情報と共に、各オプションは parser へ明示的に追加されます。 OptionParser コンストラクタへオプションのリストを引数で渡すことも可能ですが、その方法はあまり使用されないと思います。

オプションを定義する

オプションは :func:add_option() メソッドを使用して1度に1つだけ追加すべきです。引数リストの最初にある文字列はオプション名として扱います。あるオプションのエイリアスを作成するために(例えば、同じオプションを表す短いオプション名と長いオプション名を持つには)、単純に両方のオプション名を引数に渡します。

コマンドラインを解析する

すべてのオプションが定義された後で parse_args() へコマンドラインの引数文字列を渡すことで解析されます。デフォルトでは、その引数は sys.argv[1:] から取得されますが、任意のリストで明示的に渡すことができます。そのオプションは GNU/POSIX 構文を使用して処理されるので、オプションと引数の値はシーケンスに混在してセットされます。

parse_args()Values インスタンスとオプションと見なされないコマンドの引数リストの2つの値を持つタプルを返します。オプションのデフォルトアクションは add_option() への dest 引数に渡される名前を使用してその値を保持します。 parse_args() が返す Values インスタンスは属性としてオプションの値を保持します。そのため、もしオプションの dest"myoption" の場合、その値は options.myoption でアクセスします。

短いオプション名と長いオプション名

3つの異なるオプションを使用する簡単なサンプルを紹介します。ブーリアンオプション (-a)、シンプルな文字列オプション (-b)、そして整数オプション (-c) です。

import optparse

parser = optparse.OptionParser()
parser.add_option('-a', action="store_true", default=False)
parser.add_option('-b', action="store", dest="b")
parser.add_option('-c', action="store", dest="c", type="int")

print parser.parse_args(['-a', '-bval', '-c', '3'])

コマンドラインオプションは getopt.gnu_getopt() を使用するのと同じルールで解析されます。そのため、1文字オプションへ値を渡す方法が2つあります。

$ python optparse_short.py
(<Values at 0x1004d23f8: {'a': True, 'c': 3, 'b': 'val'}>, [])

実行後の出力の 'c' に対する値のデータ型が整数型であることに注意してください。それは OptionParser クラスがその値を格納する前にその引数を変換して保持するからです。

getopt と違い、 optparse は “長い” オプション名を別処理として扱いません。

import optparse

parser = optparse.OptionParser()
parser.add_option('--noarg', action="store_true", default=False)
parser.add_option('--witharg', action="store", dest="witharg")
parser.add_option('--witharg2', action="store", dest="witharg2", type="int")

print parser.parse_args([ '--noarg', '--witharg', 'val', '--witharg2=3' ])

その出力結果も似ています。

$ python optparse_long.py
(<Values at 0x1004da3f8: {'noarg': True, 'witharg': 'val', 'witharg2': 3}>, [])

getopt と比較する

optparsegetopt を置き換えるためにサポートされたので、このサンプルは getopt: のセクションで使用した同じサンプルプログラムを再実装します。

import optparse
import sys

print 'ARGV      :', sys.argv[1:]

parser = optparse.OptionParser()
parser.add_option('-o', '--output', 
                  dest="output_filename", 
                  default="default.out",
                  )
parser.add_option('-v', '--verbose',
                  dest="verbose",
                  default=False,
                  action="store_true",
                  )
parser.add_option('--version',
                  dest="version",
                  default=1.0,
                  type="float",
                  )
options, remainder = parser.parse_args()

print 'VERSION   :', options.version
print 'VERBOSE   :', options.verbose
print 'OUTPUT    :', options.output_filename
print 'REMAINING :', remainder

オプション -o--output が同時に追加されるようにエイリアス化する方法に注意してください。どちらか一方のオプションがコマンドラインで使用されます。短いオプション名で実行します。

$ python optparse_getoptcomparison.py -o output.txt
ARGV      : ['-o', 'output.txt']
VERSION   : 1.0
VERBOSE   : False
OUTPUT    : output.txt
REMAINING : []

又は、長いオプション名で実行します。

$ python optparse_getoptcomparison.py --output output.txt
ARGV      : ['--output', 'output.txt']
VERSION   : 1.0
VERBOSE   : False
OUTPUT    : output.txt
REMAINING : []

長いオプション名のユニークな接頭辞も使用することができます。

$ python optparse_getoptcomparison.py --out output.txt
ARGV      : ['--out', 'output.txt']
VERSION   : 1.0
VERBOSE   : False
OUTPUT    : output.txt
REMAINING : []

オプション値

デフォルトのアクション処理はオプションに対する引数を保持するためのものです。もし型が提供されるなら、引数の値はその値が保持される前に指定された型に変換されます。

デフォルト値の設定

オプションの指定は任意なので、アプリケーションはコマンドラインでオプションが与えられなかったときにデフォルトの振る舞いを定義すべきです。個々のオプションのデフォルト値はそのオプションが定義されたときに提供されます。

import optparse

parser = optparse.OptionParser()
parser.add_option('-o', action="store", default="default value")

options, args = parser.parse_args()

print options.o
$ python optparse_default.py
default value

$ python optparse_default.py -o "different value"
different value

また、デフォルト値はオプションが定義された後で set_defaults() に対するキーワード引数を使用して読み込むこともできます。

import optparse

parser = optparse.OptionParser()
parser.add_option('-o', action="store")

parser.set_defaults(o='default value')

options, args = parser.parse_args()

print options.o

この方法は、ハードコーディングせずに設定ファイルか、その他のソースファイルからデフォルト値を読み込むときに便利です。

$ python optparse_set_defaults.py
default value

$ python optparse_set_defaults.py -o "different value"
different value

定義された全オプションは parse_args() が返す Values インスタンスの属性として利用できます。そのため、アプリケーションはその値を使用しようとする前にオプションの存在を確認する必要がありません。

import optparse

parser = optparse.OptionParser()
parser.add_option('-o', action="store")

options, args = parser.parse_args()

print options.o

もしオプションのデフォルト値がなく、コマンドラインでも指定されなかった場合、その値は None になります。

$ python optparse_no_default.py
None

$ python optparse_no_default.py -o "different value"
different value

型変換

optparse はオプションの値を文字列から整数、小数、長整数や複雑な値へ変換します。変換を行うためには、 add_option() に対する引数としてオプションの type を指定します。

import optparse

parser = optparse.OptionParser()
parser.add_option('-i', action="store", type="int")
parser.add_option('-f', action="store", type="float")
parser.add_option('-l', action="store", type="long")
parser.add_option('-c', action="store", type="complex")

options, args = parser.parse_args()

print 'int    : %-16r %s' % (type(options.i), options.i)
print 'float  : %-16r %s' % (type(options.f), options.f)
print 'long   : %-16r %s' % (type(options.l), options.l)
print 'complex: %-16r %s' % (type(options.c), options.c)

もしオプションの値が指定された型に変換できない場合、エラーを表示してプログラムを終了します。

$ python optparse_types.py -i 1 -f 3.14 -l 1000000 -c 1+2j
int    : <type 'int'>     1
float  : <type 'float'>   3.14
long   : <type 'long'>    1000000
complex: <type 'complex'> (1+2j)

$ python optparse_types.py -i a
Usage: optparse_types.py [options]

optparse_types.py: error: option -i: invalid integer value: 'a'

Option クラスをサブクラス化することでカスタム変換を行うことができます。詳細は標準ライブラリドキュメントを参照してください。

選択肢

choice 型は候補文字列のリストを使用するバリデーションを提供します。 type に choise をセットして add_option() に対する choises 引数に有効な値リストを指定します。

import optparse

parser = optparse.OptionParser()

parser.add_option('-c', type='choice', choices=['a', 'b', 'c'])

options, args = parser.parse_args()

print 'Choice:', options.c

不正な入力を行うと、許容される値リストのエラーメッセージを表示します。

$ python optparse_choice.py -c a
Choice: a

$ python optparse_choice.py -c b
Choice: b

$ python optparse_choice.py -c d
Usage: optparse_choice.py [options]
optparse_choice.py: error: option -c: invalid choice: 'd' (choose from
 'a', 'b', 'c')

オプションのアクション

オプションの解析のみを行う getopt と違い optparse は完全なオプション 処理 ライブラリです。オプションは違うアクションのトリガーになることができます。それは add_option() への action 引数で指定されます。サポートされているアクションは、その引数を格納する(1つずつか、リストの一部)、定数の引数オプションが指定されたときに定数の値(真偽値を扱うために特化した操作も含む)を格納する、あるオプションが現れた回数をカウントする、そしてコールバック関数を呼び出すがあります。デフォルトアクションは store で、明示的に指定する必要はありません。

定数

アプリケーションの操作モードのような、オプションがある選択範囲に固定されるとき、それを分かり易くするために明示的に独立したオプションを作成します。 store_const アクションはこの目的に適しています。

import optparse

parser = optparse.OptionParser()
parser.add_option('--earth', action="store_const", const='earth', dest='element', default='earth')
parser.add_option('--air', action='store_const', const='air', dest='element')
parser.add_option('--water', action='store_const', const='water', dest='element')
parser.add_option('--fire', action='store_const', const='fire', dest='element')

options, args = parser.parse_args()

print options.element

store_const アクションは、ユーザが指定したオプションでアプリケーションの定数を関連付けます。同じ dest 名に対して違う定数値を格納するために複数のオプションが設定されるので、アプリケーションは1つの設定のみを確認する必要があります。

$ python optparse_store_const.py
earth

$ python optparse_store_const.py --fire
fire

ブーリアンフラグ

ブーリアンオプションは True や False の定数値を格納する特別なアクションを使用して実装されます。

import optparse

parser = optparse.OptionParser()
parser.add_option('-t', action='store_true', default=False, dest='flag')
parser.add_option('-f', action='store_false', default=False, dest='flag')

options, args = parser.parse_args()

print 'Flag:', options.flag

同じフラグの True や Faslse バージョンは同じ値に対する dest 名を設定することで作成されます。

$ python optparse_boolean.py
Flag: False

$ python optparse_boolean.py -t
Flag: True

$ python optparse_boolean.py -f
Flag: False

繰り返しオプション

繰り返しオプションを扱うために3つの方法があります。デフォルトは指定された最後のオプションを使用するように既存の値を上書きすることです。 store アクションはこの方法で動作します。

append アクションを使用すると、オプションが繰り返されると値を蓄積することができます。追加モードは複数の応答が返されるときに便利で、ユーザは解析可能な構文を構築するよりも簡単に指定できます。

import optparse

parser = optparse.OptionParser()
parser.add_option('-o', action="append", dest='outputs', default=[])

options, args = parser.parse_args()

print options.outputs

コマンドラインで与えられた値の順番は保持されます。それはアプリケーションによっては重要なときがあります。

$ python optparse_append.py
[]

$ python optparse_append.py -o a.out
['a.out']

$ python optparse_append.py -o a.out -o b.out
['a.out', 'b.out']

1つのオプションが何回与えられたかを知りたくて関連付けられた値が必要ではないときがあります。例えば、多くのアプリケーションは出力の冗長レベルを上げるために -v オプションを繰り返すことができます。 count アクションはそのオプションが現れる毎にその値が増加します。

import optparse

parser = optparse.OptionParser()
parser.add_option('-v', action="count", dest='verbosity', default=1)
parser.add_option('-q', action='store_const', const=0, dest='verbosity')

options, args = parser.parse_args()

print options.verbosity

-v オプションは引数を受け取らないので、個別にオプションが指定されたときと同様に -vv といった構文で繰り返すことができます。

$ python optparse_count.py
1

$ python optparse_count.py -v
2

$ python optparse_count.py -v -v
3

$ python optparse_count.py -vv
3

$ python optparse_count.py -q
0

コールバック

オプションの引数を直接保持することに加えて、コマンドラインでそのオプションが指定されたときに呼び出されるコールバック関数を定義することもできます。オプションのためのコールバック関数は4つの引数を取ります。それらはコールバックを呼び出す Option インスタンス、コマンドラインからのオプションの文字列、そのオプションに渡される引数の値、オプションの解析を行う OptionParser インスタンスです。

import optparse

def flag_callback(option, opt_str, value, parser):
    print 'flag_callback:'
    print '\toption:', repr(option)
    print '\topt_str:', opt_str
    print '\tvalue:', value
    print '\tparser:', parser
    return

def with_callback(option, opt_str, value, parser):
    print 'with_callback:'
    print '\toption:', repr(option)
    print '\topt_str:', opt_str
    print '\tvalue:', value
    print '\tparser:', parser
    return

parser = optparse.OptionParser()
parser.add_option('--flag', action="callback", callback=flag_callback)
parser.add_option('--with', 
                  action="callback",
                  callback=with_callback,
                  type="string",
                  help="Include optional feature")

parser.parse_args(['--with', 'foo', '--flag'])

このサンプルでは --with オプションが文字列の引数を取るように設定されています(同様に整数型や浮動小数点型のようなデータ型もサポートされています)。

$ python optparse_callback.py
with_callback:
        option: <Option at 0x1004d1248: --with>
        opt_str: --with
        value: foo
        parser: <optparse.OptionParser instance at 0x100468518>
flag_callback:
        option: <Option at 0x1004687a0: --flag>
        opt_str: --flag
        value: None
        parser: <optparse.OptionParser instance at 0x100468518>

コールバックは nargs オプションを使用して複数の引数を取得して設定することができます。

import optparse

def with_callback(option, opt_str, value, parser):
    print 'with_callback:'
    print '\toption:', repr(option)
    print '\topt_str:', opt_str
    print '\tvalue:', value
    print '\tparser:', parser
    return

parser = optparse.OptionParser()
parser.add_option('--with', 
                  action="callback",
                  callback=with_callback,
                  type="string",
                  nargs=2,
                  help="Include optional feature")

parser.parse_args(['--with', 'foo', 'bar'])

このケースでは、引数は value 引数で1つのタプルとしてコールバック関数へ渡されます。

$ python optparse_callback_nargs.py
with_callback:
        option: <Option at 0x1004676c8: --with>
        opt_str: --with
        value: ('foo', 'bar')
        parser: <optparse.OptionParser instance at 0x100467440>

ヘルプメッセージ

OptionParser は自動的に全てのオプションセットに対して --help オプションを追加します。そのため、ユーザはコマンドラインで --help を指定することで、プログラム実行のためのヘルプを確認することができます。

import optparse

parser = optparse.OptionParser()
parser.add_option('--no-foo', action="store_true", 
                  default=False, 
                  dest="foo",
                  help="Turn off foo",
                  )
parser.add_option('--with', action="store", help="Include optional feature")

parser.parse_args()

オプションは同行にエイリアスも追加してアルファベット順に表示されます。そのオプションが引数を取るとき dest にセットした名前はヘルプ出力において引数の名前になります。ヘルプのテキストは右側のカラムに表示されます。

$ python optparse_help.py --help
Usage: optparse_help.py [options]

Options:
  -h, --help   show this help message and exit
  --no-foo     Turn off foo
  --with=WITH  Include optional feature

そのオプションが対象とする変数として WITH という名前が --with オプションと一緒に表示されます。プログラム内の変数名がそのドキュメントを提供するのに適切な場合は違う名前をセットするために metavar 引数を使用します。

import optparse

parser = optparse.OptionParser()
parser.add_option('--no-foo', action="store_true", 
                  default=False, 
                  dest="foo",
                  help="Turn off foo",
                  )
parser.add_option('--with', action="store", help="Include optional feature",
                  metavar='feature_NAME')

parser.parse_args()

大文字もしくは句読点への変更を行わず、その値が与えられたものとして正確に表示されます。

$ python optparse_metavar.py -h
Usage: optparse_metavar.py [options]

Options:
  -h, --help           show this help message and exit
  --no-foo             Turn off foo
  --with=feature_NAME  Include optional feature

オプションを構成する

多くのアプリケーションは関連するオプションセットを含みます。例えば rpm コマンドはそれぞれの操作モードに応じた独立したオプションを含みます。 optparse はヘルプ出力のオプションを構成するために option groups を使用します。それでも全てのオプションの値は1つの Values インスタンスに保存されます。そのため、オプション名の名前空間もフラットな状態です。

import optparse

parser = optparse.OptionParser()

parser.add_option('-q', action='store_const', const='query', dest='mode',
                  help='Query')
parser.add_option('-i', action='store_const', const='install', dest='mode',
                  help='Install')

query_opts = optparse.OptionGroup(
    parser, 'Query Options',
    'These options control the query mode.',
    )
query_opts.add_option('-l', action='store_const', const='list', dest='query_mode',
                      help='List contents')
query_opts.add_option('-f', action='store_const', const='file', dest='query_mode',
                      help='Show owner of file')
query_opts.add_option('-a', action='store_const', const='all', dest='query_mode',
                      help='Show all packages')
parser.add_option_group(query_opts)

install_opts = optparse.OptionGroup(
    parser, 'Installation Options',
    'These options control installation.',
    )
install_opts.add_option('--hash', action='store_true', default=False,
                        help='Show hash marks as progress indication')
install_opts.add_option('--force', dest='install_force', action='store_true', default=False,
                        help='Install, regardless of depdencies or existing version')
parser.add_option_group(install_opts)

print parser.parse_args()

それぞれのグループはタイトルと説明の独自セクションを持ちます。また、そのオプションは一緒に表示されます。

$ python optparse_groups.py -h
Usage: optparse_groups.py [options]

Options:
  -h, --help  show this help message and exit
  -q          Query
  -i          Install

  Query Options:
    These options control the query mode.

    -l        List contents
    -f        Show owner of file
    -a        Show all packages

  Installation Options:
    These options control installation.

    --hash    Show hash marks as progress indication
    --force   Install, regardless of depdencies or existing version

アプリケーション設定

自動的なヘルプ生成機能は複数のヘルプ出力の外観を扱うための設定をサポートしています。プログラムの usage 文字列は、 OptionParser が作成されたときに引数の位置がどうであるかを表示します。

import optparse

parser = optparse.OptionParser(usage='%prog [options] <arg1> <arg2> [<arg3>...]')
parser.add_option('-a', action="store_true", default=False)
parser.add_option('-b', action="store", dest="b")
parser.add_option('-c', action="store", dest="c", type="int")

parser.parse_args()

%prog というリテラルは実行時にプログラムの名前に展開されます。そのため、スクリプトに対するフルパスが反映されます。 python コマンドでそのスクリプトを実行する場合、直接的に実行されずにそのスクリプト名が使用されます。

$ python optparse_usage.py -h
Usage: optparse_usage.py [options] <arg1> <arg2> [<arg3>...]

Options:
  -h, --help  show this help message and exit
  -a
  -b B
  -c C

プログラム名は prog 引数を使用して変更することができます。

import optparse

parser = optparse.OptionParser(usage='%prog [options] <arg1> <arg2> [<arg3>...]',
                               prog='my_program_name',
                               )
parser.add_option('-a', action="store_true", default=False)
parser.add_option('-b', action="store", dest="b")
parser.add_option('-c', action="store", dest="c", type="int")

parser.parse_args()

この方法のようにプログラム名をハードコーディングすることは一般的には悪い考えです。とは言うものの、もしプログラムがリネームされるなら、そのヘルプはその名前変更に影響を受けません。

$ python optparse_prog.py -h
Usage: my_program_name [options] <arg1> <arg2> [<arg3>...]

Options:
  -h, --help  show this help message and exit
  -a
  -b B
  -c C

アプリケーションのバージョンは version 引数を使用して設定します。バージョンが指定されたときに optparse は自動的にパーサへ --version オプションを追加します。

import optparse

parser = optparse.OptionParser(usage='%prog [options] <arg1> <arg2> [<arg3>...]',
                               version='1.0',
                               )

parser.parse_args()

ユーザが --version オプションでそのプログラムを実行するとき optparse はバージョン文字列を表示して終了します。

$ python optparse_version.py -h
Usage: optparse_version.py [options] <arg1> <arg2> [<arg3>...]

Options:
  --version   show program's version number and exit
  -h, --help  show this help message and exit

$ python optparse_version.py --version
1.0

See also

optparse
本モジュールの標準ライブラリドキュメント
getopt
optparse により置き換えられる getopt モジュール
argparse
optparse に置き換わる新たなモジュール
Bookmark and Share