Issue 26181: argparse can't handle positional argument after list (help message is wrong) (original) (raw)

This code is meant to take a filename and a list of integers as arguments. The filename is required, the integers are optional:

import argparse parser = argparse.ArgumentParser() parser.add_argument('filename') parser.add_argument('-L', metavar='integer', type=int, nargs='+') args = parser.parse_args() print(args) # see what we got

It produces the following help message: usage: demo.py [-h] [-L integer [integer ...]] filename

However, the filename argument does not work if it's given in that position (after the list of ints). Instead, it tries to use filename as another list element:

$ python demo.py -L 1 2 3 test.txt usage: demo.py [-h] [-L integer [integer ...]] filename demo.py: error: argument -L: invalid int value: 'test.txt'

Changing the order of the arguments works as intended:

$ python demo.py test.txt -L 1 2 3 Namespace(L=[1, 2, 3], filename='test.txt')

Probably the simplest fix would be to amend the help message to show the positional argument before the list:

usage: demo.py [-h] filename [-L integer [integer ...]]

There are 2 issues

parsing - how to reserve one or more arguments for use by following 'positionals'. Fixes have been proposed in other bug/issues, but aren't trivial.

usage formatting - the stock formatter displays all optionals first, followed by all positionals. In a multiline display positionals go on a new line.

Changes to the help formatter that would block this reordering have been discussed on Stackoverflow, but I don't recall such an issue here. It can be done by changing one method in a subclassed formatter.

The immediate solution is to give your parser a custom usage line - one that puts the positional in the correct order.