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: Missing subparser error message should be more clear
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.7
process
Status: closed Resolution: duplicate
Dependencies: Superseder: argparse fails with required subparsers, un-named dest, and empty argv
View: 29298
Assigned To: Nosy List: jacobtylerwalls, paul.j3, porton
Priority: normal Keywords:

Created on 2018-07-22 19:58 by porton, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (4)
msg322164 - (view) Author: Victor Porton (porton) Date: 2018-07-22 19:58
argparse produces a long unreadable, non-understandable for non-programmers error message when a subparser is not specified in the command line.

Note that the below message contains Ubuntu specifics, but it seems it would be nearly as unclear on other OSes too.

The worst thing about this error message is that to produce something readable instead I need to somehow parse the command string (or at least to catch TypeError).

$ python3.7 test.py 
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    args = parser.parse_args()
  File "/usr/lib/python3.7/argparse.py", line 1754, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib/python3.7/argparse.py", line 1786, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib/python3.7/argparse.py", line 2021, in _parse_known_args
    ', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 24, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

Original exception was:
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    args = parser.parse_args()
  File "/usr/lib/python3.7/argparse.py", line 1754, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "/usr/lib/python3.7/argparse.py", line 1786, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "/usr/lib/python3.7/argparse.py", line 2021, in _parse_known_args
    ', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found

The script follows.

#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser(description="Automatically process XML")
subparsers = parser.add_subparsers(title='subcommands')

chain_parser = subparsers.add_parser('chain', aliases=['c'], help='Automatically run a chain of transformations')

args = parser.parse_args()
msg322229 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-07-23 16:16
Your code runs fine under 3.6.5.

But if I add 'subparsers.required=True', I get your error.  It's having problems formatting the name of the subparsers command when issuing the error message.

If I add a 'dest' to the add_subparsers I get the expected error message:

    import argparse

    parser = argparse.ArgumentParser(description="Automatically process XML")
    subparsers = parser.add_subparsers(title='subcommands', dest='cmd')
    subparsers.required=True
    chain_parser = subparsers.add_parser('chain', aliases=['c'], 
        help='Automatically run a chain of transformations')

    args = parser.parse_args()
    print(args)

The default 'dest' for subparsers is None, and the error arises from

    ','.join([None])

The problems with a missing 'dest' came up in earlier discussions about making required/not required subparsers.  3.7 made subparsers 'required' by default, but it appears that it hasn't addressed this missing 'dest' problem.

But I haven't followed the latest release details closely.
msg322241 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-07-23 18:53
Updating you Python3.7 might change the behavior.  If I read

https://github.com/python/cpython/commits/master/Lib/argparse.py

correctly, subparsers are no longer required by default (it reverted back to earlier Py3 behavior).  There is a proposed patch for handling this 'dest=None' issue, but I don't think that's been pushed.

But simply adding the 'dest' to subparses should work without update.  If you want to identify which subparser was used, you need this 'dest'.
msg412615 - (view) Author: Jacob Walls (jacobtylerwalls) * Date: 2022-02-06 03:44
Duplicate of issue29298 (fixed)
History
Date User Action Args
2022-04-11 14:59:03adminsetgithub: 78372
2022-02-08 03:47:56ned.deilysetstatus: open -> closed
superseder: argparse fails with required subparsers, un-named dest, and empty argv
resolution: duplicate
stage: resolved
2022-02-06 03:44:07jacobtylerwallssetnosy: + jacobtylerwalls
messages: + msg412615
2018-07-23 18:53:52paul.j3setmessages: + msg322241
2018-07-23 16:16:37paul.j3setnosy: + paul.j3
messages: + msg322229
2018-07-22 19:58:30portoncreate