问题
Here's a subsection of my parser configuration
parser.add_argument(
'infile', help="The file to be imported",
type=argparse.FileType('r'), default=sys.stdin
)
parser.add_argument(
'--carpark', nargs='+', dest='CarparkID', type=int, default=[],
help="One or many carpark IDs"
)
However, the --carpark argument seems to be too greedy and eats anything that follows it:
$ mycommand --carpark 17 ~/path-to-file
mycommand: error: argument --carpark: invalid int value: '/home/oli/path-to-file'
What's a good way around something like this? I need to pass a list of integer IDs into the command but also have a positional file (which can also be stdin).
Is there —for example— a non-greedy nargs option that will only parse as much of this as makes sense?
回答1:
If you want to specify multiple car park IDs, I would do one of two things instead of using nargs='+':
Use the option once per ID (
mycommand --carpark 17 --carpark 18)parser.add_argument('--carpark', dest='carpark_ids', type=int, action='append', default=[], help="One carpark ID (can be used multiple times)" )Take a single, comma-delimited argument instead (
mycommand --carpark 17,18)parser.add_argument('--carpark', type=lambda s: map(int, s.split(",")), dest='carpark_ids', default=[], help="One or more carpark IDs" )With a little more work, you could modify this to allow multiple uses of
--carparkto accumulate all its values into a single list.
A third alternative, one I'm not particularly fond of, is to abandon the positional argument, making it an optional argument instead. (mycommand --carpark 17 18 --infile ~/path-to-file).
parser.add_argument('--infile',
help="The file to be imported",
type=argparse.FileType('r'),
default=sys.stdin
)
parser.add_argument('--carpark',
nargs='+',
dest='CarparkID',
type=int, default=[],
help="One or many carpark IDs"
)
回答2:
Does this work?
$ mycommand ~/path-to-file --carpark 17
There is a Python bug/issue over + Actions that consume too many arguments, leaving none for following Actions.
The argument allocation is based on argument counts, not on type. The type function is applied after allocation, and there's no provision for returning 'rejected' arguments.
In correct behavior it should take into account that infile is expecting an argument - and there aren't any further flag strings - and thus reserve one string to that Action.
I could look that bug/issue up, but for now the fix is to supply the arguments in a different order. Or define a --infile action (instead of the positional).
An earlier question, with the bug/issue link (my answer focuses more on getting the usage right).
Argparse - do not catch positional arguments with `nargs`.
来源:https://stackoverflow.com/questions/36328769/argparse-nargs-is-eating-positional-argument