Is it possible to use a regex for parsing an argument? For example, I want to accept an argument if only it is a 32 length hex (i.e. matches /[a-f0-9A-F]{32}/)
I tried
p.add_argument('hex', type=str, nargs="[a-f0-9A-F]{32}")
without success
The type keyword for add_argument() can take any callable that accepts a single string argument and returns the converted value. If the callable raises argparse.ArgumentTypeError, TypeError, or ValueError, the exception is caught and a nicely formatted error message is displayed.
import argparse
import re
from uuid import uuid4
def my_regex_type(arg_value, pat=re.compile(r"^[a-f0-9A-F]{32}$")):
if not pat.match(arg_value):
raise argparse.ArgumentTypeError("invalid value")
return arg_value
parser = argparse.ArgumentParser()
parser.add_argument('hex', type=my_regex_type)
args = parser.parse_args([uuid4().hex])
Improving on wim's answer, you can wrap the regex-checking function as a closure which allows you to reuse the regex checking function with other patterns.
regex_type(pattern) returns a function which, when passed to the type keyword argument, checks the string argument against pattern.
import argparse
import re
def regex_type(pattern: str | re.Pattern):
"""Argument type for matching a regex pattern."""
def closure_check_regex(arg_value):
if not re.match(pattern, arg_value):
raise argparse.ArgumentTypeError("invalid value")
return arg_value
return closure_check_regex
parser = argparse.ArgumentParser()
parser.add_argument("hex", type=regex_type(r"^[a-f0-9A-F]{32}$"))
# Example
from uuid import uuid4
args = parser.parse_args([uuid4().hex]) # this succeeds
args = parser.parse_args(["not-valid"]) # >>> error: argument hex: invalid value
# Reusing the regex_type
parser.add_argument("digits", type=regex_type(r"^\d+$"))
argparsedoes useregexexpressions to count argument strings, but it generates the patterns itself. The allowednargsvalues like*+?' have a regex feel, but they aren't used directly. They are actually values of module constants (likeargparse.ZERO_OR_MORE), and are used inif else` tests.