0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonのargparse.ArgumentParser.add_argumentでEnumをchoicesする

Last updated at Posted at 2024-09-28

動機

PythonでCLIスクリプトを作成するとき、起動時のオプション解釈には argparse を使う。
argparse では引数に制限を加えたい場合、 choices オプションが使える。

from argparse import ArgumentParser
p = ArgumentParser()
p.add_argument('mode', choices=['walk','run','stop'])

p.parse_args(['-h'])
# positional arguments:
#   {walk,run,stop}

p.parse_args(['walk'])
# Namespace(mode='walk')

p.parse_args(['stand'])
# python: error: argument mode: invalid choice: 'stand' (choose from 'walk', 'run', 'stop')

ただ、やはりマジックコードをスクリプトに埋め込むのはよくない。
そこで列挙型である enum と組み合わせたい。

問題

しかし、そのまま何もしないとヘルプの表示が崩れるうえ、そもそもちゃんと解析できない。

from enum import Enum
class ACTION(Enum):
    WALK = 'walk'
    RUN = 'run'
    STOP = 'stop'

from argparse import ArgumentParser
p = ArgumentParser()
p.add_argument('mode', choices=ACTION)

p.parse_args(['-h'])
# positional arguments:
#   {ACTION.WALK,ACTION.RUN,ACTION.STOP} ←変!

p.parse_args(['walk'])
# TypeError: unsupported operand type(s) for 'in': 'str' and 'EnumMeta'

解決策

下記2点で解決する。

  • ヘルプの表示を直すために ACTION.__str__ を定義して、オプション文字列のみを返す
  • 解析エラーを直すために add_argumenttype を指定する

具体的には下記の通り。

from enum import Enum
class ACTION(Enum):
    WALK = 'walk'
    RUN = 'run'
    STOP = 'stop'

    def __str__(self): # これを定義!
        return self.value

from argparse import ArgumentParser
p = ArgumentParser()
p.add_argument('mode', choices=ACTION, type=ACTION) # type を指定!

p.parse_args(['-h'])
# positional arguments:
#   {walk,run,stop} ←いいかんじ!

p.parse_args(['walk'])
# => Namespace(mode=<ACTION.WALK: 'walk'>) ← ちゃんと解析できた!

補足知識

Enum は値で呼び出すと、その要素を返してくれる。
(ドキュメントに書かれていない動作?)
リファレンスではなくてチュートリアルに記載がありました: 列挙型メンバーおよびそれらの属性へのプログラム的アクセス

from enum import Enum
class ACTION(Enum):
    WALK = 'walk'
    RUN = 'run'
    STOP = 'stop'

ACTION('walk')
# => <ACTION.WALK: 'walk'>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?