I have read through a bunch of the questions already answered, but I don't see this covered--at least not that I recognized.
I am using argparse to take a file and convert it to a different type. The input filename is required. The output filename is NOT required as the optional argument should handle that. Here is the code so far:
import sys
import argparse
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('--json', type=str, help='Converts to json format')
parser.add_argument('--bibtex', type=str, help='Converts to bibtex format')
parser.add_argument('--html', type=str, help='Converts to html format')
parser.add_argument('inputfilename', type=str, help='enter the original filename')
args = parser.parse_args()
filename=args.filename
if args.json:
print('Converting to json ...')
#conversion code here
elif args.bibtex:
print('Converting to bibtex ...')
#conversion code here
elif args.html:
print('Converting to html ...')
#conversion code here
else:
print('No conversion type indicated')
The problem is that whenever I use one of these flags. If I do
$ ./orsconvert.py --json inputfilename
I get an error saying
orsconvert.py: error: the following arguments are required: inputfilename
It does this because it interprets the provided inputfilename
as an outputfilename connected to the --json
. It is trying to force me to actually state the output filename after the optional argument and before the input filename, similar to this:
$ ./orsconvert.py --json outputfilename inputfileneame
However, I do not want to do that if there is a way around it. I want it to accept --json
as the indication of what to do and then use inputfilename
as the input and automatically save it as outputfilename
according to what the code will specify.
Yes, I am looking at making the 3 optional arguments a group to simplify the code ... but that still doesn't explain how to get it to not require another argument after the optional one and before the final inputfilename
required argument.
Is there something else I can put in the parser.add_argument('...')
field that will stop requiring me to specify an outputfilename
? I would like to change the code as little as possible because I am already pushing the limits of my coding comprehension.
The problem is that you defined --json
to require an argument, and it's taking the input file name as that argument. Your three converters should use the store_true
action, not the default store
action.
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('--json', action='store_true', help='Converts to json format')
parser.add_argument('--bibtex', action='store_true', help='Converts to bibtex format')
parser.add_argument('--html', action='store_true', help='Converts to html format')
parser.add_argument('inputfilename', help='enter the original filename')
args = parser.parse_args()
With this change, args.json
et all are the Boolean values you expect them to be. The store_true
action takes care of defining the type to be bool
and the default value to be false
.
Better yet, though, would be a single required positional argument that must take the value json
, bibtex
, or html
. Then parse_args
itself would detect if an incorrect or missing conversion type was given.
parser = argparse.ArgumentParser(description='Convert file to new type')
parser.add_argument('inputfilename', help='enter the original filename')
parser.add_argument('conversion_type', choices=['json', 'bibtex', 'html'])
args = parser.parse_args()
filename = args.filename
conversion_type = args.conversion_type # Guaranteed to be json, html, or bibtex
if conversion_type == "json":
...
elif conversion_type == "bibtex":
...
elif conversion_type == "html":
If you would like an option with a default value, buckle up :) We're going to add 4 options: one that lets specify the output type explicitly, and three shortcuts for setting it.
p = argparse.ArgumentParser()
p.add_argument('inputfilename')
p.add_argument('--type', choices=['json', 'bibtex', 'html'], default='json')
p.add_argument('--json', action='store_const', const='json', dest='type')
p.add_argument('--html', action='store_const', const='html', dest='type')
p.add_argument('--bibtex', action='store_const', const='bibtex', dest='type')
--json
, --bibtex
, and --html
have the same effect as --type json
, --type bibtex
, and --type html
, respectively. As before, --type
can only take those three values as its argument. If more than one of these, the last one used takes effect.