Your custom action is the closest way to how it is done internally for other argument types. IMHO there should be a _StoreCommaSeperatedAction added to argparse in the stdlib since it is a somewhat common and useful argument type,
It can be used with an added default as well.
Here is an example without using an action (no SplitArgs class):
class Test:
def __init__(self):
self._names: List[str] = ["Jane", "Dave", "John"]
@property
def names(self):
return self._names
@names.setter
def names(self, value):
self._names = [name.strip() for name in value.split(",")]
test_object = Test()
parser = ArgumentParser()
parser.add_argument(
"-n",
"--names",
dest="names",
default=",".join(test_object.names), # Joining the default here is important.
help="a comma separated list of names as an argument",
)
print(test_object.names)
parser.parse_args(namespace=test_object)
print(test_object.names)
Here is another example using SplitArgs class inside a class completely
"""MyClass
Demonstrates how to split and use a comma separated argument in a class with defaults
"""
import sys
from typing import List
from argparse import ArgumentParser, Action
class SplitArgs(Action):
def __call__(self, parser, namespace, values, option_string=None):
# Be sure to strip, maybe they have spaces where they don't belong and wrapped the arg value in quotes
setattr(namespace, self.dest, [value.strip() for value in values.split(",")])
class MyClass:
def __init__(self):
self.names: List[str] = ["Jane", "Dave", "John"]
self.parser = ArgumentParser(description=__doc__)
self.parser.add_argument(
"-n",
"--names",
dest="names",
default=",".join(self.names), # Joining the default here is important.
action=SplitArgs,
help="a comma separated list of names as an argument",
)
self.parser.parse_args(namespace=self)
if __name__ == "__main__":
print(sys.argv)
my_class = MyClass()
print(my_class.names)
sys.argv = [sys.argv[0], "--names", "miigotu, sickchill,github"]
my_class = MyClass()
print(my_class.names)
And here is how to do it in a function based situation, with a default included
class SplitArgs(Action):
def __call__(self, parser, namespace, values, option_string=None):
# Be sure to strip, maybe they have spaces where they don't belong and wrapped the arg value in quotes
setattr(namespace, self.dest, [value.strip() for value in values.split(",")])
names: List[str] = ["Jane", "Dave", "John"]
parser = ArgumentParser(description=__doc__)
parser.add_argument(
"-n",
"--names",
dest="names",
default=",".join(names), # Joining the default here is important.
action=SplitArgs,
help="a comma separated list of names as an argument",
)
parser.parse_args()