Reputation: 1982
Is there a way to add an argument to ArgumentParser for an np.array instead of a list? I know I can do something like this
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('-foo', action='store', type=int, nargs='+')
args = parser.parse_args(['-foo', '1', '2'])
args.foo = np.array(args.foo)
But I would like to specify the complete description of the arguments before parsing.
Is there a way to do this?
Upvotes: 2
Views: 4654
Reputation: 21453
To specify a slight change in how the StoreAction
action handler works you would create a subclass of the handler with appropriate change (the docs have an example right above this section)
import argparse, numpy as np
class Store_as_array(argparse._StoreAction):
def __call__(self, parser, namespace, values, option_string=None):
values = np.array(values)
return super().__call__(parser, namespace, values, option_string)
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('-foo', action=Store_as_array, type=int, nargs='+')
# ^ specify as the action
args = parser.parse_args(['-foo', '1', '2'])
assert isinstance(args.foo, np.ndarray)
Upvotes: 4
Reputation: 231510
As indicated in my comment, 'complete description before parsing' is unclear.
But it occurred to me that it is possible to create a 2d array with argparse
. I can use nargs=3
to specify 3 columns, and action='append'
to collect the input in multiple sublists. And of course type
specifies whether it int or float.
In [27]: p=argparse.ArgumentParser()
In [28]: p.add_argument('-a',action='append',nargs='+',type=int)
Out[28]: _AppendAction(option_strings=['-a'], dest='a', nargs='+', const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)
In [29]: args=p.parse_args('-a 1 2 3 -a 4 5 6 -a 7 8 9'.split())
In [30]: args
Out[30]: Namespace(a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [31]: np.array(args.a)
Out[31]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
It will complain if I don't have the right number of columns. All it doesn't control is the number of rows; but I can easily check the shape of the array after creation.
With this append
it doesn't make sense to create the array in the action
. And even with the 1d input, there isn't much of an advantage to performing that np.array
call during parsing. Massaging (and testing) the args
values after parsing is perfectly good practice.
It would better, though to put the array values in a CSV file, and specify the name of that file via argparse
. argparse
really isn't meant for input of a large number of values. It's not a general purpose file parser. The command line controls the behavior of your code.
Upvotes: 2