argparseのヘルプメッセージ改行位置を変更する方法

Pythonのコマンドラインツール開発では`argparse`がオプションパーサとしてよく利用されます。argparseによるヘルプメッセージ表示機能で「いや、そんな微妙なところで改行しないでよ...」って思うことが最近ありました。

本記事では、そういった場面で`argparse`によるヘルプメッセージ改行位置を変更する方法について紹介します。

# 微妙なヘルプメッセージ改行例

```python:argparse_bad_help_msg.py
import argparse

desc = "ArgParse Test Program"
parser = argparse.ArgumentParser(description=desc)
parser.add_argument("--input", help="Input data", metavar="")
parser.add_argument("--output", help="Output data", metavar="")
parser.add_argument("--parameter1", help="Parameter 1", metavar="")
parser.add_argument("--long_name_parameter2", help="Long name parameter2", metavar="")
parser.add_argument("--parameter3", help="Parameter 3", metavar="")
parser.add_argument("--long_name_parameter4", help="Long name parameter4", metavar="")

args = parser.parse_args()
```

```text:微妙な位置でのヘルプメッセージ改行
$ python argparse_bad_help_msg.py --help
usage: argparse_bad_help_msg.py [-h] [--input] [--output] [--parameter1] [--long_name_parameter2] [--parameter3] [--long_name_parameter4]

ArgParse Test Program

optional arguments:
  -h, --help            show this help message and exit
  --input               Input data
  --output              Output data
  --parameter1          Parameter 1
  --long_name_parameter2 
                        Long name parameter2
  --parameter3          Parameter 3
  --long_name_parameter4 
                        Long name parameter4
```
オプション文字列が長い場合に、微妙な位置で改行が入っています。オプション文字列がもっと長い場合にはこれでも構わないですが、個人的にはこの程度であれば改行してほしくありません。

# ヘルプメッセージ改行仕様

https://docs.python.org/ja/3/library/argparse.html#argumentparser-objects

argparseの公式ドキュメントを参照すると、`ArgumentParser`オブジェクトの`formatter_class`引数からヘルプ出力をカスタマイズできると記述があります。formatter_class引数にはデフォルトで`HelpFormatter`クラスが指定されます。
HelpFormatterの実装を見ると、コンストラクタ引数にヘルプメッセージ改行位置を決定する`max_help_position`パラメータ(Default=24)があります。そのため、このパラメータを変更することでヘルプメッセージ改行位置を変更できるような仕様だと分かります。

```python:HelpFormatterコンストラクタ
class HelpFormatter(object):
    def __init__(self, prog, indent_increment=2, max_help_position=24, width=None):
        # 〜〜〜以下略〜〜〜
```

# ヘルプメッセージ改行位置の変更実装例

HelpFormatterを継承したCustomHelpFormatterクラスでヘルプメッセージ改行位置を変更するように実装してみた。

```python:argparse_good_help_msg.py
import argparse

class CustomHelpFormatter(argparse.HelpFormatter):
    # 'max_help_position'のデフォルト値を「24」から「30」へ変更
    def __init__(self, prog, indent_increment=2, max_help_position=30, width=None):
        super().__init__(prog, indent_increment, max_help_position, width)

desc = "ArgParse Test Program"
parser = argparse.ArgumentParser(description=desc, formatter_class=CustomHelpFormatter)
parser.add_argument("--input", help="Input data", metavar="")
parser.add_argument("--output", help="Output data", metavar="")
parser.add_argument("--parameter1", help="Parameter 1", metavar="")
parser.add_argument("--long_name_parameter2", help="Long name parameter2", metavar="")
parser.add_argument("--parameter3", help="Parameter 3", metavar="")
parser.add_argument("--long_name_parameter4", help="Long name parameter4", metavar="")

args = parser.parse_args()
```

```text:微妙な位置でのヘルプメッセージ改行の解消結果
$ python argparse_good_help_msg.py --help
usage: argparse_good_help_msg.py [-h] [--input] [--output] [--parameter1] [--long_name_parameter2] [--parameter3] [--long_name_parameter4]

ArgParse Test Program

optional arguments:
  -h, --help               show this help message and exit
  --input                  Input data
  --output                 Output data
  --parameter1             Parameter 1
  --long_name_parameter2   Long name parameter2
  --parameter3             Parameter 3
  --long_name_parameter4   Long name parameter4
```

微妙な位置でのヘルプメッセージ改行が解消され、すっきりした見た目にすることができた。