動作を確認した際の環境
- Python 3.13.1
- jsonargparse 4.45.0
jsonargparse 4.46.0では、この現象は発生しません。期待通りパースされます。
何が起きたか
整数を受け取るCLI引数を用意したいです。ただし、受け取る整数は1か2のいずれかにしたいです。
argparse.ArgumentParserならば以下のように書けます。
from argparse import ArgumentParser
def create_parser() -> ArgumentParser:
parser = ArgumentParser()
parser.add_argument(
"--depth",
type=int,
choices=[1, 2],
)
return parser
args = create_parser().parse_args()
print(args)
$ python sample1_argparse.py --help
usage: sample1_argparse.py [-h] [--depth {1,2}]
options:
-h, --help show this help message and exit
--depth {1,2}
$ python sample1_argparse.py --depth 1
Namespace(depth=1)
jsonargparse.ArgumentParserならばヘルプメッセージにデフォルト値を表示してくれるので、argparse.ArgumentParserではなくjsonargparse.ArgumentParserを使うことにしました。
しかし、--depth 1を期待通り受け取れませんでした。
from jsonargparse import ArgumentParser
def create_parser() -> ArgumentParser:
parser = ArgumentParser()
parser.add_argument(
"--depth",
type=int,
choices=[1, 2],
)
return parser
args = create_parser().parse_args()
print(args)
$ python sample1_jsonargparse.py --help
usage: sample1_jsonargparse.py [--depth {1,2}]
options:
-h, --help Show this help message and exit.
--depth {1,2} (type: int, default: null)
$ python sample1_jsonargparse.py --depth 1
usage: sample1_jsonargparse.py [--depth {1,2}]
tip: For details of accepted options run: sample1_jsonargparse.py --help
error: argument --depth: invalid choice: '1' (choose from 1, 2)
この現象は、すでにissueで報告されていました。
2026/01/08に以下のpull requestにより、このissueは閉じられました。
https://github.com/omni-us/jsonargparse/pull/827
v4.46.0では、期待通りの挙動に修正されました。
$ python sample1_jsonargparse.py --depth 1
Namespace(depth=1)
解決策
--depthを整数でなく文字列を受け取るように変更して、対応しました。単純な対応です。
from jsonargparse import ArgumentParser
def create_parser() -> ArgumentParser:
parser = ArgumentParser()
parser.add_argument(
"--depth",
type=str,
choices=["1", "2"],
)
return parser
args = create_parser().parse_args()
print(args)
$ python sample2_jsonargparse.py --help
usage: sample2_jsonargparse.py [--depth {1,2}]
options:
-h, --help Show this help message and exit.
--depth {1,2} (type: str, default: null)
$ python sample2_jsonargparse.py --depth 1
Namespace(depth='1')
なお、issueに対する作者からの返信にある通り、Enumを使うのも良いかもしれません。
For the time being, as a workaround, consider using an Enum as a type. 1
ただし、今回の例の--depthに対してはEnumは使わない方がよいと思います。one,twoという情報のない名前しか付けられないためです。
from enum import IntEnum
from jsonargparse import ArgumentParser
class Depth(IntEnum):
one = 1
two = 2
parser = ArgumentParser()
parser.add_argument("--depth", type=Depth)
args = parser.parse_args()
print(args)
$ python sample3_jsonargparse.py --help
usage: sample3_jsonargparse.py [--depth {one,two}]
options:
-h, --help Show this help message and exit.
--depth {one,two} (type: Depth, default: null)
$ python sample3_jsonargparse.py --depth one
Namespace(depth=<Depth.one: 1>)
補足
argparse.ArgumentParserでは、型変換後にchoicesを比較しています。
Note that choices are checked after any type conversions have been performed, so objects in choices should match the type specified. This can make choices appear unfamiliar in usage, help, or error messages. 2