I have the following code
parser = argparse.ArgumentParser(allow_abbrev=False, add_help=False)
parser.add_argument('--conf', nargs=1)
parser.add_argument('-h', '--help', nargs='?', const='generic')
parser.add_argument('-v', '--version', action="store_true")
subparsers = parser.add_subparsers()
subparsers.required = False
parser_start = subparsers.add_parser('start')
group1 = parser_start.add_mutually_exclusive_group()
group1.add_argument('--quiet', action="store_true")
group1.add_argument('-V', '--verbose', nargs="*")
# parser_console = subparsers.add_parser('console')
print(argv)
parsed_args = parser.parse_known_args(argv)
Now, when I pass argv
as argv = ['abc', 'def']
or argv = ['abc']
I get
['abc', 'def']
usage: lbrynet [--conf CONF] [-h [HELP]] [-v] {start} ...
lbrynet: error: invalid choice: 'abc' (choose from 'start')
What I was expecting was to get ['abc', 'def']
in the tuple for unknown args. I've checked a lot of stackoverflow answers(such as ans 1 , ans 2 , ans 3 , ans 4 ) and bug reports(eg br 1 ) and a lot but I can't seem to find a way to do it. Is this an unsolved bug? Am I wrong in expecting that this can be done. If this can't be done are there any workarounds to doing this?
Also to clarify, the ['abc', 'def']
got from the tuple have to be passed to some other function to be processed.
Happy to provide any further clarifications and/or clear any ambiguities.
As I wrote in a comment, subparsers is a positional argument.
To illustrate with a plain positional:
In [307]: parser = argparse.ArgumentParser()
In [308]: a1 = parser.add_argument('foo')
In [309]: parser.parse_known_args(['one','two'])
Out[309]: (Namespace(foo='one'), ['two'])
'one' is allocated to the first positional. Now give foo
choices:
In [310]: a1.choices = ['bar','test']
In [311]: parser.parse_known_args(['one','two'])
usage: ipython3 [-h] {bar,test}
ipython3: error: argument foo: invalid choice: 'one' (choose from 'bar', 'test')
It is still trying to allocate the first string to foo
. Since it doesn't match choices
, it raises an error.
In [312]: parser.parse_known_args(['bar','one','two'])
Out[312]: (Namespace(foo='bar'), ['one', 'two'])
Strings are assigned to positionals based on position, not on value. Any value checking, such as with type or choices is done after assignment.
Change the choices
to a type
test:
In [313]: a1.choices = None
In [314]: a1.type = int
In [315]: parser.parse_known_args(['bar','one','two'])
usage: ipython3 [-h] foo
ipython3: error: argument foo: invalid int value: 'bar'
In [316]: parser.parse_known_args(['12','one','two'])
Out[316]: (Namespace(foo=12), ['one', 'two'])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.