Search code examples
pythonargparse

Python argparse - optional argument 'overriding' required one


I'm looking for a way to have the following behavior with argparse.

Imagine as an example that I want a program that pretty print a file given as input. And I also want an optional argument to display the list of file types that the program handles. What I'd like is the following behavior.

myparser ./myfile.json

> this would pretty print the file myfile.json

myparser --list

> this would display the list of handled file types

However, I don't see how to do it: in the second line, argparse asks me to provide the filepath argument.

So I could either do what I want by doing myparser . --list and code the program such that the filepath argument is ignored when the list argument is provided.

Or I could set the filepath argument as optional, which would require me to do the following:

myparser --filepath ./myfile.json

Both solutions work fine, but I'm still curious about if it is possible to have the behavior that I want. Do you have any solution ? (Remark that the behavior that I'm looking for is exactly the one of the help argument)


Solution

  • First, just for contrast, you need to make the file name optional. That means providing an explicit --print option instead of a required file name, so that your usage is either

    myparser --print ./myfile.json
    

    or

    myparser --list
    

    Closer to what you actually want is to define a custom action that exits your script early, much like version or help.

    class ListAction(argparse.Action):
        def __init__(self, option_strings, dest=argparse.SUPPRESS, default=argparse.SUPPRESS, help=None):
            super().__init__(option_strings=option_strings, nargs=0, dest=dest, default=default, help=help)
    
        def __call__(self, parser, namespace, values, option_string=None):
            print("Hello world")
            parser.exit()
    
    p = argparse.ArgumentParser()
    p.add_argument('name')
    p.add_argument('--list', action=ListAction)
    

    Now myparser --list will process --list and exit before it notices that the required filename option is missing.

    (The definition of ListAction is modeled explicitly after the definition of argparse._HelpAction.)