Argparse チュートリアル
***********************

このチュートリアルでは、"argparse" を丁寧に説明します。 "argparse" は
、Python 標準ライブラリの一部であり、おすすめのコマンドライン引数の解
析モジュールです。

注釈:

  標準ライブラリには、コマンドライン引数の処理に直接関係するライブラリ
  が、ほかに 2 つあります。 より低水準の "optparse" モジュールは、アプ
  リケーションに合わせた設定に多くのコードが必要な場合もありますが、
  "argparse" がサポートしない動作を指定できます。 さらに低水準の
  "getopt" は、C プログラマが使う "getopt()" 系の関数に相当するもので
  す。 このガイドでは、これらのモジュールを直接は取り上げません。 ただ
  し、"argparse" の主要な概念の多くは "optparse" に由来するため、この
  チュートリアルの一部は "optparse" の利用者にも役立ちます。


コンセプト
==========

**ls** コマンドを使って、このチュートリアルで私たちが学ぶ機能をいくつ
か見てみましょう:

   $ ls
   cpython  devguide  prog.py  pypy  rm-unused-function.patch
   $ ls pypy
   ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...
   $ ls -l
   total 20
   drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
   drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide
   -rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py
   drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy
   -rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch
   $ ls --help
   Usage: ls [OPTION]... [FILE]...
   List information about the FILEs (the current directory by default).
   Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
   ...

上の４つの実行結果から、以下のことが分かります:

* **ls** コマンドは、まったくオプションを指定せずに実行したとしても役
  に立ちます。デフォルトの動作は、カレントディレクトリの内容を表示する
  ことです。

* デフォルト以外の動作をさせるには、追加の情報を渡します。 この例では
  、別のディレクトリ "pypy" の内容を表示させるために、位置引数と呼ばれ
  るものを指定しました。 コマンドライン上の位置だけで、プログラムがそ
  の値の用途を判断できることから、この名前が付いています。 この考え方
  は **cp** のようなコマンドではさらに重要です。 最も基本的な使い方は
  "cp SRC DEST" で、最初の位置は *コピーしたいもの*、2 番目の位置は *
  コピー先* を表します。

* プログラムの振る舞いを変えましょう。例では、単にファイル名を表示する
  代わりにそれぞれのファイルに関する多くの情報を表示します。このケース
  では、"-l" はoptional引数として知られます。

* ヘルプテキストの抜粋です。この実行の仕方は、まだ使用したことがないプ
  ログラムにたいして行うと有用で、ヘルプテキストを読むことで、プログラ
  ムがどのように動作するかわかります。


基礎
====

（ほとんど）何もしない、とても簡単な例から始めましょう:

   import argparse
   parser = argparse.ArgumentParser()
   parser.parse_args()

下記がこのコードを実行した結果です:

   $ python prog.py
   $ python prog.py --help
   usage: prog.py [-h]

   options:
     -h, --help  show this help message and exit
   $ python prog.py --verbose
   usage: prog.py [-h]
   prog.py: error: unrecognized arguments: --verbose
   $ python prog.py foo
   usage: prog.py [-h]
   prog.py: error: unrecognized arguments: foo

こんなことが起こりました:

* オプションなしでスクリプトを実行した結果、なにも標準出力に表示されま
  せんでした。それほど便利ではありませんね。

* 二つ目の実行結果から "argparse" モジュールの有用性がわかります。ほと
  んど何もしていないのに、すてきなヘルプメッセージが手に入りました。

* "--help" (短く "-h" とも書けます) は、こちらで定義せずに使える唯一の
  オプションです。 それ以外を指定するとエラーになりますが、その場合も
  追加の実装なしで役立つ使用方法のメッセージが表示されます。


位置引数の入門
==============

以下に例を示します:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("echo")
   args = parser.parse_args()
   print(args.echo)

このコードを実行してみましょう:

   $ python prog.py
   usage: prog.py [-h] echo
   prog.py: error: the following arguments are required: echo
   $ python prog.py --help
   usage: prog.py [-h] echo

   positional arguments:
     echo

   options:
     -h, --help  show this help message and exit
   $ python prog.py foo
   foo

こんなことが起こりました:

* プログラムが受け付けるコマンドラインオプションを指定するメソッドであ
  る "add_argument()" を追加しました。ここでは、その機能にあわせて引数
  名を "echo" としました。

* プログラムを実行すると、オプションを指定するように要求されます。

* "parse_args()" メソッドは、指定されたオプションから得たデータを返し
  ます。 この例では "echo" に指定された値です。

* この変数は "argparse" が自動的に行うある種の魔法です（つまり、値を格
  納する変数を指定する必要がありません）。変数の名前がメソッドに与えた
  文字列引数 "echo" と同じことに気付いたでしょう。

ヘルプメッセージは十分なように見えますが、それほど分かりやすくもありま
せん。たとえば、"echo" は位置引数であることがわかりますが、それが何で
あるかを知るためには推測するかソースコードを見なけれなりません。もうす
こしヘルプメッセージ分かりやすくしてみましょう:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("echo", help="echo the string you use here")
   args = parser.parse_args()
   print(args.echo)

修正した結果は以下のようになります:

   $ python prog.py -h
   usage: prog.py [-h] echo

   positional arguments:
     echo        echo the string you use here

   options:
     -h, --help  show this help message and exit

次は、もっと有益なことをしてみませんか？:

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

下記がこのコードを実行した結果です:

   $ python prog.py 4
   Traceback (most recent call last):
     File "prog.py", line 5, in <module>
       print(args.square**2)
   TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

上手くいきませんでした。 何も伝えなければ、"argparse" は与えられたオプ
ションを文字列として扱います。 "argparse" にオプションの値を整数として
扱うように伝えましょう:

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

下記がこのコードを実行した結果です:

   $ python prog.py 4
   16
   $ python prog.py four
   usage: prog.py [-h] square
   prog.py: error: argument square: invalid int value: 'four'

今度は上手くいきました。このプログラムは不正な入力が与えられるとそれを
処理せずに、より親切なメッセージを表示して実行を終了します。


Optional引数の導入
==================

ここまで位置引数を扱ってきました。optional引数を追加する方法についても
見ていきましょう:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("--verbosity", help="increase output verbosity")
   args = parser.parse_args()
   if args.verbosity:
       print("verbosity turned on")

実行してみましょう:

   $ python prog.py --verbosity 1
   verbosity turned on
   $ python prog.py
   $ python prog.py --help
   usage: prog.py [-h] [--verbosity VERBOSITY]

   options:
     -h, --help            show this help message and exit
     --verbosity VERBOSITY
                           increase output verbosity
   $ python prog.py --verbosity
   usage: prog.py [-h] [--verbosity VERBOSITY]
   prog.py: error: argument --verbosity: expected one argument

こんなことが起こりました:

* プログラムは、"--verbosity" が指定された場合はなにかしらを表示し、指
  定されなければ何も表示をしないように書かれています。

* オプションの指定が実際に任意であることを示すために、プログラムをオプ
  ション指定なしで実行してもエラーにはなっていません。オプション引数が
  指定されなかった場合、関連する変数、この例では "args.verbosity" 、の
  値にはデフォルトで "None" がセットされます。これが "if" 文による真偽
  テストに失敗した理由です。

* ヘルプメッセージが少し変わりました。

* "--verbosity" オプションを使うには、そのオプションにひとつの値を指定
  しなければなりません。

上記の例では、"--verbosity" に任意の整数を取れます。この簡単なプログラ
ムでは、実際には "True" または "False" の二つの値だけが有効です。そう
なるようにコードを修正してみましょう:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("--verbose", help="increase output verbosity",
                       action="store_true")
   args = parser.parse_args()
   if args.verbose:
       print("verbosity turned on")

実行してみましょう:

   $ python prog.py --verbose
   verbosity turned on
   $ python prog.py --verbose 1
   usage: prog.py [-h] [--verbose]
   prog.py: error: unrecognized arguments: 1
   $ python prog.py --help
   usage: prog.py [-h] [--verbose]

   options:
     -h, --help  show this help message and exit
     --verbose   increase output verbosity

こんなことが起こりました:

* オプションは値を必要とするのではなく、単なるフラグになりました。この
  考え方に沿うようにオプションの名前も変更しています。ここで新しいキー
  ワード "action" を指定し、値として ""store_true"" を設定していること
  に注意してください。これは、オプションが指定された場合に値として
  "True" を "args.verbose" に設定するということを意味します。オプショ
  ンの指定がない場合の値は "False" となることを意味します。

* フラグは値を取るべきではないので、値を指定するとプログラムはエラーに
  なります。

* ヘルプテキストが変わっています。


短いオプション
--------------

コマンドラインになれていれば、オプションの短いバージョンの話題に触れて
いないことに気付いたでしょう。それはとても簡単です:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("-v", "--verbose", help="increase output verbosity",
                       action="store_true")
   args = parser.parse_args()
   if args.verbose:
       print("verbosity turned on")

上記のプログラムを実行するとこうなります:

   $ python prog.py -v
   verbosity turned on
   $ python prog.py --help
   usage: prog.py [-h] [-v]

   options:
     -h, --help     show this help message and exit
     -v, --verbose  increase output verbosity

新しい機能がヘルプテキストにも反映されている点に気付いたでしょう。


位置引数とOptional引数の併用
============================

プログラムが複雑になってきました:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("square", type=int,
                       help="display a square of a given number")
   parser.add_argument("-v", "--verbose", action="store_true",
                       help="increase output verbosity")
   args = parser.parse_args()
   answer = args.square**2
   if args.verbose:
       print(f"the square of {args.square} equals {answer}")
   else:
       print(answer)

出力は以下のようになります:

   $ python prog.py
   usage: prog.py [-h] [-v] square
   prog.py: error: the following arguments are required: square
   $ python prog.py 4
   16
   $ python prog.py 4 --verbose
   the square of 4 equals 16
   $ python prog.py --verbose 4
   the square of 4 equals 16

* 位置引数を元に戻したので、引数を指定しないとエラーになりました。

* 指定する順序は関係ありません。

複数の詳細レベルを値にとれるようにプログラムを元に戻して、指定された値
を使ってみましょう:

   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,
                       help="increase output verbosity")
   args = parser.parse_args()
   answer = args.square**2
   if args.verbosity == 2:
       print(f"the square of {args.square} equals {answer}")
   elif args.verbosity == 1:
       print(f"{args.square}^2 == {answer}")
   else:
       print(answer)

実行してみましょう:

   $ python prog.py 4
   16
   $ python prog.py 4 -v
   usage: prog.py [-h] [-v VERBOSITY] square
   prog.py: error: argument -v/--verbosity: expected one argument
   $ python prog.py 4 -v 1
   4^2 == 16
   $ python prog.py 4 -v 2
   the square of 4 equals 16
   $ python prog.py 4 -v 3
   16

プログラムのバグである最後の結果を除いて、上手く行っているようです。こ
のバグを、"--verbosity" オプションが取れる値を制限することで修正しまし
ょう:

   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(f"the square of {args.square} equals {answer}")
   elif args.verbosity == 1:
       print(f"{args.square}^2 == {answer}")
   else:
       print(answer)

実行してみましょう:

   $ python prog.py 4 -v 3
   usage: prog.py [-h] [-v {0,1,2}] square
   prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
   $ python prog.py 4 -h
   usage: prog.py [-h] [-v {0,1,2}] square

   positional arguments:
     square                display a square of a given number

   options:
     -h, --help            show this help message and exit
     -v, --verbosity {0,1,2}
                           increase output verbosity

変更がエラーメッセージとヘルプメッセージの両方に反映されていることに注
意してください。

詳細レベルついて、違ったアプローチを試してみましょう。これは CPython
実行可能ファイルがその詳細レベル引数を扱う方法と同じです。（ "python
--help" の出力を確認してください）:

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

もう一つの action である "count" を紹介します。これは指定されたオプシ
ョンの出現回数を数えます:

   $ python prog.py 4
   16
   $ python prog.py 4 -v
   4^2 == 16
   $ python prog.py 4 -vv
   the square of 4 equals 16
   $ python prog.py 4 --verbosity --verbosity
   the square of 4 equals 16
   $ python prog.py 4 -v 1
   usage: prog.py [-h] [-v] square
   prog.py: error: unrecognized arguments: 1
   $ python prog.py 4 -h
   usage: prog.py [-h] [-v] square

   positional arguments:
     square           display a square of a given number

   options:
     -h, --help       show this help message and exit
     -v, --verbosity  increase output verbosity
   $ python prog.py 4 -vvv
   16

* 前のバージョンのスクリプトのようにフラグ ("action="store_true"" に似
  ています）になりました。エラーとなる理由がわかります。（訳注: ５つ目
  の例では "-v" オプションに引数を与えたため、エラーとなっています。）

* これは"store_true" アクションによく似た動作をします。

* では "count" アクションが何をもたらすかデモンストレーションをします
  。おそらくこのような使用方法を前に見たことがあるでしょう。

* "-v" フラグを指定しなければ、フラグの値は "None" とみなされます。

* 期待通り、長い形式のフラグを指定しても同じ結果になります。

* 残念ながら、このヘルプ出力はプログラムが新しく得た機能についてそこま
  で有益ではありません。しかし、スクリプトのドキュメンテーションを改善
  することでいつでも修正することができます（例えば、"help" キーワード
  引数を使用することで）。

* 最後の出力はプログラムにバグがあることを示します。

修正しましょう:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("square", type=int,
                       help="display a square of a given number")
   parser.add_argument("-v", "--verbosity", action="count",
                       help="increase output verbosity")
   args = parser.parse_args()
   answer = args.square**2

   # バグ修正: == を >= に置き換える
   if args.verbosity >= 2:
       print(f"the square of {args.square} equals {answer}")
   elif args.verbosity >= 1:
       print(f"{args.square}^2 == {answer}")
   else:
       print(answer)

これが結果です:

   $ python prog.py 4 -vvv
   the square of 4 equals 16
   $ python prog.py 4 -vvvv
   the square of 4 equals 16
   $ python prog.py 4
   Traceback (most recent call last):
     File "prog.py", line 11, in <module>
       if args.verbosity >= 2:
   TypeError: '>=' not supported between instances of 'NoneType' and 'int'

* 最初の出力はうまくいき、先ほどのバグが直りました。 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", action="count", default=0,
                       help="increase output verbosity")
   args = parser.parse_args()
   answer = args.square**2
   if args.verbosity >= 2:
       print(f"the square of {args.square} equals {answer}")
   elif args.verbosity >= 1:
       print(f"{args.square}^2 == {answer}")
   else:
       print(answer)

もう一つのキーワード引数である "default" を導入しました。整数値と比較
できるように、その値に "0" を設定しました。デフォルトでは、optional 引
数が指定されていない場合 "None" となること、"None" が整数値と比較でき
ない（よって "TypeError" 例外となる）ことを思い出してください。

こうなりました:

   $ python prog.py 4
   16

ここまで学んできたことだけで、さまざまな事が実現できます。しかしまだ表
面をなぞっただけです。 "argparse" モジュールはとても強力ですので、チュ
ートリアルを終える前にもう少しだけ探検してみましょう.


もうちょっとだけ学ぶ
====================

もし、この小さなプログラムを二乗以外の累乗が行えるように拡張するとどう
なるでしょうか:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("x", type=int, help="the base")
   parser.add_argument("y", type=int, help="the exponent")
   parser.add_argument("-v", "--verbosity", action="count", default=0)
   args = parser.parse_args()
   answer = args.x**args.y
   if args.verbosity >= 2:
       print(f"{args.x} to the power {args.y} equals {answer}")
   elif args.verbosity >= 1:
       print(f"{args.x}^{args.y} == {answer}")
   else:
       print(answer)

出力:

   $ python prog.py
   usage: prog.py [-h] [-v] x y
   prog.py: error: the following arguments are required: x, y
   $ python prog.py -h
   usage: prog.py [-h] [-v] x y

   positional arguments:
     x                the base
     y                the exponent

   options:
     -h, --help       show this help message and exit
     -v, --verbosity
   $ python prog.py 4 2 -v
   4^2 == 16

これまで、出力されるテキストを *変更する* ために詳細レベルを使ってきま
した。かわりに下記の例では、*追加の* テキストを出力するのに詳細レベル
を使用します:

   import argparse
   parser = argparse.ArgumentParser()
   parser.add_argument("x", type=int, help="the base")
   parser.add_argument("y", type=int, help="the exponent")
   parser.add_argument("-v", "--verbosity", action="count", default=0)
   args = parser.parse_args()
   answer = args.x**args.y
   if args.verbosity >= 2:
       print(f"Running '{__file__}'")
   if args.verbosity >= 1:
       print(f"{args.x}^{args.y} == ", end="")
   print(answer)

出力:

   $ python prog.py 4 2
   16
   $ python prog.py 4 2 -v
   4^2 == 16
   $ python prog.py 4 2 -vv
   Running 'prog.py'
   4^2 == 16


多義性のある引数の指定
----------------------

ある引数の解釈について、位置引数なのか、ある引数に対する追加の引数なの
か、あいまいさがあるときは、 "--" を使うことで "parse_args()" に対して
これ以降は位置引数であることを伝えることができます:

   >>> parser = argparse.ArgumentParser(prog='PROG')
   >>> parser.add_argument('-n', nargs='+')
   >>> parser.add_argument('args', nargs='*')

   >>> # 曖昧なので、parse_args はオプションと解釈する
   >>> parser.parse_args(['-f'])
   usage: PROG [-h] [-n N [N ...]] [args ...]
   PROG: error: unrecognized arguments: -f

   >>> parser.parse_args(['--', '-f'])
   Namespace(args=['-f'], n=None)

   >>> # 曖昧なので、-n オプションは引数を取れるだけ取る
   >>> parser.parse_args(['-n', '1', '2', '3'])
   Namespace(args=[], n=['1', '2', '3'])

   >>> parser.parse_args(['-n', '1', '--', '2', '3'])
   Namespace(args=['2', '3'], n=['1'])


競合するオプション
------------------

これまで "argparse.ArgumentParser" インスタンスの 2 つのメソッドを使っ
てきました。 3 つ目の "add_mutually_exclusive_group()" を紹介しましょ
う。 このメソッドでは、互いに同時指定できないオプションを定義できます
。 新しい機能の意味が伝わるよう、プログラムのほかの部分も変更し、"--
verbose" と反対の働きをする "--quiet" オプションを導入します。

   import argparse

   parser = argparse.ArgumentParser()
   group = parser.add_mutually_exclusive_group()
   group.add_argument("-v", "--verbose", action="store_true")
   group.add_argument("-q", "--quiet", action="store_true")
   parser.add_argument("x", type=int, help="the base")
   parser.add_argument("y", type=int, help="the exponent")
   args = parser.parse_args()
   answer = args.x**args.y

   if args.quiet:
       print(answer)
   elif args.verbose:
       print(f"{args.x} to the power {args.y} equals {answer}")
   else:
       print(f"{args.x}^{args.y} == {answer}")

プログラムは簡単になり、説明のためにいくつかの機能を省きました。 出力
を見てみましょう。

   $ python prog.py 4 2
   4^2 == 16
   $ python prog.py 4 2 -q
   16
   $ python prog.py 4 2 -v
   4 to the power 2 equals 16
   $ python prog.py 4 2 -vq
   usage: prog.py [-h] [-v | -q] x y
   prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
   $ python prog.py 4 2 -v --quiet
   usage: prog.py [-h] [-v | -q] x y
   prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose

これは分かりやすいでしょう。ここで得たちょっとした柔軟性を示すために最
後の出力を追加しました、つまり長い形式のオプションと短い形式のオプショ
ンの混在です。

結びの前に、恐らくあなたはプログラムの主な目的をユーザに伝えたいでしょ
う。万が一、彼らがそれを知らないときに備えて:

   import argparse

   parser = argparse.ArgumentParser(description="calculate X to the power of Y")
   group = parser.add_mutually_exclusive_group()
   group.add_argument("-v", "--verbose", action="store_true")
   group.add_argument("-q", "--quiet", action="store_true")
   parser.add_argument("x", type=int, help="the base")
   parser.add_argument("y", type=int, help="the exponent")
   args = parser.parse_args()
   answer = args.x**args.y

   if args.quiet:
       print(answer)
   elif args.verbose:
       print(f"{args.x} to the power {args.y} equals {answer}")
   else:
       print(f"{args.x}^{args.y} == {answer}")

使用方法のテキストが少し変化しました。"[-v | -q]" は "-v" または "-q"
のどちらかを使用できるが、同時に両方を使用できないことを意味します:

   $ python prog.py --help
   usage: prog.py [-h] [-v | -q] x y

   calculate X to the power of Y

   positional arguments:
     x              the base
     y              the exponent

   options:
     -h, --help     show this help message and exit
     -v, --verbose
     -q, --quiet


argparse の出力を翻訳するには
=============================

ヘルプテキストやエラーメッセージなどの "argparse" モジュールの出力は、
すべて "gettext" モジュールを使って訳せるように作られています。これに
より、 "argparse" によって生成されたメッセージを簡単にローカライズでき
ます。 プログラムやモジュールを国際化する も参照してください。

たとえば、この "argparse" の出力では:

   $ python prog.py --help
   usage: prog.py [-h] [-v | -q] x y

   calculate X to the power of Y

   positional arguments:
     x              the base
     y              the exponent

   options:
     -h, --help     show this help message and exit
     -v, --verbose
     -q, --quiet

文字列 "usage:", "positional arguments:", "options:" と "show this
help message and exit" はすべて訳せます。

これらの文字列を訳すには、それらをまず ".po" ファイルに抽出する必要が
あります。たとえば、 Babel を使い、次のコマンドを実行します。

   $ pybabel extract -o messages.po /usr/lib/python3.12/argparse.py

このコマンドは "argparse" モジュールからすべての翻訳可能な文字列を抽出
し、それらを "messages.po" という名前のファイルに出力します。このコマ
ンドは Python のインストールが "/usr/lib" にあることを前提としています
。

システム上の "argparse" モジュールの場所は、次のスクリプトで調べられま
す:

   import argparse
   print(argparse.__file__)

".po" ファイル内のメッセージが訳され、その訳が "gettext" を用いてイン
ストールされると、 "argparse" は翻訳されたメッセージを表示できるように
なります。

"argparse" 出力内のあなたの文字列を翻訳するには、 "gettext" を使います
。


独自の型変換
============

"argparse" モジュールでは、コマンドライン引数に独自の型変換処理を指定
できます。 これにより、利用者の入力を "argparse.Namespace" に格納する
前に変換できます。 プログラムで入力を使う前に前処理が必要な場合に役立
ちます。

独自の型変換処理には、引数の値を表す文字列を 1 つ受け取り、変換した値
を返す任意の呼び出し可能オブジェクトを使えます。 もっと複雑な処理が必
要な場合は、代わりに **action** 引数で独自のアクションクラスを指定でき
ます。

例えば、異なるプレフィクスの引数を受け取り、それぞれに応じて処理したい
とします。

   import argparse

   parser = argparse.ArgumentParser(prefix_chars='-+')

   parser.add_argument('-a', metavar='<value>', action='append',
                       type=lambda x: ('-', x))
   parser.add_argument('+a', metavar='<value>', action='append',
                       type=lambda x: ('+', x))

   args = parser.parse_args()
   print(args)

出力:

   $ python prog.py -a value1 +a value2
   Namespace(a=[('-', 'value1'), ('+', 'value2')])

この例では、次のことを行っています。

* "prefix_chars" 引数を使い、独自のプレフィクス文字を持つパーサを作り
  ました。

* "-a" と "+a" という 2 つの引数を定義しました。 それぞれの "type" 引
  数で独自の型変換処理を指定し、値をプレフィクスと一緒にタプルに格納す
  るようにしました。

独自の型変換処理がなければ、"-a" と "+a" は同じ引数として扱われ、望ま
しくない結果になります。 型変換処理を使うことで、2 つの引数を区別でき
ました。


結び
====

"argparse" モジュールはここで学んだことより多くの機能を提供します。モ
ジュールのドキュメントはとても詳細で、綿密で、そしてたくさんの例があり
ます。このチュートリアルの体験したことで、気がめいることなくそれらの他
の機能を会得できるに違いありません。
