I am writing a script that will be used to merge several input files, generating a single output file, and I want to build a small command line interface using argparse
. To me, the most natural-seeming way to do it would be to have a single optional input, -i
, which takes one or more input file names, followed by a positional argument, representing the output file name. Here's an example of what I had in mind:
#!/usr/bin/env python3
"""
Script for merging input files
"""
import argparse
script_docstring = 'Read some input files and create a merged output.'
parser = argparse.ArgumentParser(description=script_docstring)
# Optional input file names
parser.add_argument('-i --inputs', nargs='+', type=str, required=True,
help='Input file names', dest='inputs')
# Positional output file name
parser.add_argument('fname_out', type=str, help='Output file name')
args = parser.parse_args()
# Display what the user chose at the command line
print(args.inputs)
print(args.fname_out)
When I print the auto-generated help message created by argparse
, the call signature looks like what I had intended:
> ./mergefiles.py --help
usage: mergefiles.py [-h] -i --inputs INPUTS [INPUTS ...] fname_out
Read some input files and create a merged output.
positional arguments:
fname_out Output file name
optional arguments:
-h, --help show this help message and exit
-i --inputs INPUTS [INPUTS ...]
Input file names
However, when I actually attempt to run the script, it gives an error which suggests to me that argparse
is mistakenly parsing the final positional argument as though it were to be included amongst the list of optionals:
> ./mergefiles.py -i a.in b.in c.in test.out
usage: mergefiles.py [-h] -i --inputs INPUTS [INPUTS ...] fname_out
mergefiles.py: error: the following arguments are required: fname_out
My question: Is it even possible to get argparse
to handle a case such as this correctly, treating the final argument as a positional? Or is my only option to accept a "workaround" solution such as turning the output file name into an optional argument as well, e.g., like -f --fname_out
or similar.
If it's not possible to do what I want, then I plan to implement exactly that as my fallback solution. However, before I accept an inelegant workaround, I'm curious whether it's actually possible to get argparse
to handle this the "correct" way.