python / cpython

The Python programming language
https://www.python.org
Other
63.55k stars 30.45k forks source link

Argparse help string incorrectly places named arguments #105947

Open stevielb opened 1 year ago

stevielb commented 1 year ago

Bug report

When defining a named argument, argparse will always place it before the positional arguments even when it is defined later. This can create an incorrect help string when nargs='+' because argparse will treat your positional arguments incorrectly if you actually try to follow the help string.

Repro:

parser = argparse.ArgumentParser()
parser.add_argument('foo')
parser.add_argument('--bar', nargs='+')
parser.parse_args(['-h'])

Expected

usage: myprog [-h] foo [--bar BAR] Argument can be used as suggested: myprog foovalue --bar barvalue1 barvalue2

Actual

usage: myprog [-h] [--bar BAR] foo Argument cannot be used as suggested: myprog --bar barvalue1 barvalue2 foovalue results in error: the following arguments are required: foo

Your environment

Python 3.10.4

hpaulj commented 1 year ago

Yes, the usage routinely reorders the arguments, putting the positional last. In the case of multiline usage, positionals go on a new line. That is consistent with common POSIX practice,

The usage generator is not "smart" enough to detect cases like this where the suggested order raises errors. In a major rewrite of the usage, we could have the option of turning off this reordering, but for now the existing method is too brittle to accomodate such a change.

You can, as programmer, provide a custom usage string.

serhiy-storchaka commented 1 month ago

Actual usage output is

usage: [-h] [--bar BAR [BAR ...]] foo

So you can see that --bar takes arbitrary number of arguments, but at least one.

You can use -- to separate optional arguments from positional: myprog --bar barvalue1 barvalue2 -- foovalue.

As a workarouns you can specify custom usage. Specify also prog and usage to subparsers if you use subparsers.

Leaving this issue open just in case somebody improve help or whatever. This is unlikely to happen.