This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: argparse crashes on subparsers with no dest/metava
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: closed Resolution: duplicate
Dependencies: Superseder:
Assigned To: Nosy List: paul.j3, rhettinger, terence.honles, terry.reedy
Priority: normal Keywords:

Created on 2021-04-16 19:07 by terence.honles, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25446 closed terence.honles, 2021-04-16 19:07
Messages (8)
msg391250 - (view) Author: Terence Honles (terence.honles) * Date: 2021-04-16 19:07
When creating a simple required subparser the following will result in an error instead of an error message:

>>> from argparse import ArgumentParser
>>>
>>> parser = ArgumentParser()
>>> subparsers = parser.add_subparsers(required=True)
>>> subparsers.add_parser('one')
>>> subparsers.add_parser('two')
>>>
>>> parser.parse_args([])

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.8/argparse.py", line 1768, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib64/python3.8/argparse.py", line 1800, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib64/python3.8/argparse.py", line 2035, in _parse_known_args
    ', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found

Looking at the code this is because the subparser is actually an action and when resolving the name it uses `None` as the subparser name which results in the error above.
msg391323 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2021-04-18 05:46
This is a well known (if not fixed) issue - if subparsers is required, then a dest is needed to give a working error message.  Looks like we've variously talked about documenting the requirement, or using some sort of substitute for the missing name.

One of my higher-voted SO answers: 

https://stackoverflow.com/questions/23349349/argparse-with-required-subparser/23354355#23354355

https://bugs.python.org/issue29298

https://github.com/python/cpython/pull/18564

https://github.com/python/cpython/pull/3027

https://github.com/python/cpython/pull/3680
msg391324 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-04-18 05:51
Would it be more reasonable to provide a default name (which is what the PR does) or to raise an exception?
msg391339 - (view) Author: Terence Honles (terence.honles) * Date: 2021-04-18 17:53
Thanks for the context Paul. I didn't think to look in the tracker for an existing issue, sorry!

I'm not sure if documenting the requirement is sufficient or something that a user would go towards with the error as it is.

I _might_ suggest throwing an error if dest/metavar isn't provided when required is true but that would probably only work on creating the sub parser and not if setting attributes as I saw some tests doing.

If an error is thrown I'd expect it to be where I placed the default name and it to basically say sub parser has no name (and possibly suggest setting dest or metavar).

I think both might be confusing to the end user and likely something that a user relying on argparse might not test but expect to work (I am in that camp except I tested it... I was only wondering what it said). That is why I went with filling out the default of "command" (I also checked only one sub parser was allowed so that wouldn't be too ambiguous). Initially I went with "subcommand" because "subparser" didn't seem to make sense for an end user, but I settled with command since that's what some tests were using for dest and I liked it. I had also thought of expanding to all the options as one of the comments had in the other issue, but required argument: {command1,command2,...} looked a little funny and was less obvious what it meant since it could also looked like N arguments were missing and being represented in a collapsed representation.
msg391794 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-04-24 19:27
Terence, a 'crash' for this tracker is a core dump or equivalent with no exception/traceback.
msg391805 - (view) Author: Terence Honles (terence.honles) * Date: 2021-04-24 21:34
Sorry I didn't know what to put, and now that you changed it I understand what behavior means. Thanks for changing it.

Should I do anything further? Not sure how to proceed.
msg391831 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-04-25 01:46
Wait for responses
msg398849 - (view) Author: Terence Honles (terence.honles) * Date: 2021-08-03 18:54
Closing as a duplicate of https://bugs.python.org/issue29298 (which was recently merged and caused conflicts with my patch)
History
Date User Action Args
2022-04-11 14:59:44adminsetgithub: 88040
2021-08-03 18:54:24terence.honlessetstatus: open -> closed
resolution: duplicate
messages: + msg398849

stage: patch review -> resolved
2021-04-25 01:46:44terry.reedysetmessages: + msg391831
2021-04-24 21:34:58terence.honlessetmessages: + msg391805
2021-04-24 19:27:10terry.reedysetversions: - Python 3.6, Python 3.7
nosy: + terry.reedy

messages: + msg391794

type: crash -> behavior
stage: patch review
2021-04-18 17:53:47terence.honlessetmessages: + msg391339
2021-04-18 05:51:42rhettingersetmessages: + msg391324
2021-04-18 05:46:28paul.j3setmessages: + msg391323
2021-04-18 04:15:37rhettingersetnosy: + rhettinger, paul.j3
2021-04-16 19:07:46terence.honlescreate