2

Is there a way to filetype-check filename arguments using argparse? Seems like it could be done via the type or choices keyword if I can create the right type of container object.

I'm expecting a type of file passed in (say, file.txt) and want argparse to give its automatic message if the file is not of the right type (.txt). For example, argparse might output

usage: PROG --foo filename etc... error: argument filename must be of type *.txt.

Perhaps instead of detecting the wrong filetype, we could try to detect that filename string did not end with '.txt' but that would require a sophisticated container object.

1
  • options.foo.endswith(".txt") or test the mime type. you should also have a look at docopt github.com/docopt/docopt Commented Oct 19, 2012 at 15:44

3 Answers 3

6

You can use the type= keyword to specify your own type converter; if your filename is incorrect, throw a ArgumentTypeError:

import argparse

def textfile(value):
    if not value.endswith('.txt'):
        raise argparse.ArgumentTypeError(
            'argument filename must be of type *.txt')
    return value

The type converter doesn't have to convert the value..

parser.add_argument('filename', ..., type=textfile)
Sign up to request clarification or add additional context in comments.

3 Comments

Perhaps this is just me being nit-picky, but I prefer actions for these sorts of things because you're taking an action based on the input -- You aren't converting the type. That said, this is an entirely workable solution (and it's probably slightly easier to implement than mine) (+1).
@mgilson: Well, the type callables have two functions: validation and conversion of an argument type. In this case we only validate, as no conversion is needed; the input is already of the right python type..
@mgilson I think using type is more appropriate, easier and with less possible side effects, using action requires you to know about inner machinery of argparse and do call setattr
2

Sure. You can create a custom action:

class FileChecker(argparse.Action):
    def __init__(self,parser,namespace,filename,option_string=None):
        #code here to check the file, e.g...
        check_ok = filename.endswith('.txt')
        if not check_ok:
           parser.error("useful message here")
        else:
           setattr(namespace,self.dest,filename)

and then you use that as the action:

parser.add_argument('foo',action=FileChecker)

Comments

1

I usually use 'type' argument to do such checking

import argparse

def foo_type(path):
    if not path.endswith(".txt"):
        raise argparse.ArgumentTypeError("Only .txt files allowed")
    return path

parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help', type=foo_type)
args = parser.parse_args()

example:

$ python argp.py --foo not_my_type
usage: argp.py [-h] [--foo FOO]
argp.py: error: argument --foo: Only .txt files allowed

2 Comments

Isn't this the same as the answer by @MartijnPieters?
yes but when I posted it there was no answer to this question :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.