Is it possible when using the argparse module to add validation when parsing arguments?
from argparse import ArgumentParser parser = ArgumentParser(description='Argument parser for PG restore') parser.add_argument('--database', dest='database', default=None, required=False, help='Database to restore') parser.add_argument('--backup', dest='backup', required=True, help='Location of the backup file') parsed_args = parser.parse_args()
Would it be possible, to add a validation check to this argument parser, to make sure the backup file / database exist? Rather than having to add an extra check after this for every parameter such as:
from os.path import exists if not database_exists(parsed_args.database): raise DatabaseNotFoundError if not exists(parsed_args.backup): raise FileNotFoundError
The argparse.FileType
is a type
factory class that can open a file, and of course, in the process raise an error if the file does not exist or cannot be created. You could look at its code to see how to create your own class (or function) to test your inputs.
The argument type
parameter is a callable (function, etc) that takes a string, tests it as needed, and converts it (as needed) into the kind of value you want to save to the args
namespace. So it can do any kind of testing you want. If the type
raises an error, then the parser creates an error message (and usage) and exits.
Now whether that's the right place to do the testing or not depends on your situation. Sometimes opening a file with FileType
is fine, but then you have to close it yourself, or wait for the program to end. You can't use that open file in a with open(filename) as f:
context. The same could apply to your database. In a complex program you may not want to open or create the file right away.
I wrote for a Python bug/issue a variation on FileType
that created a context
, an object that could be used in the with
context. I also used os
tests to check if the file existed or could be created, without actually doing so. But it required further tricks if the file
was stdin/out
that you don't want to close. Sometimes trying to do things like this in argparse
is just more work than it's worth.
Anyways, if you have an easy testing method, you could wrap it in a simple type
function like this:
def database(astring): from os.path import exists if not database_exists(astring): raise ValueError # or TypeError, or `argparse.ArgumentTypeError return astring parser.add_argument('--database', dest='database', type = database, default=None, required=False, help='Database to restore')
I don't think it matters a whole lot whether you implement testing like this in the type
or Action
. I think the type
is simpler and more in line with the developer's intentions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With