Shinomoto Asakura
Shinomoto Asakura

Reputation: 1542

How to pass an argument calling a function using ArgParse?

I'm trying to call function_3 with an argument but i'm receiving a error unrecognized arguments. I'm calling this way: python script.py --pass test

import argparse
import sys

def function_1():
    print('Function 1')

def function_2():
    print('Function 2')

def function_3(arg):
    print(f'Function 3 {arg}')

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()
    
    parser_f1 = subparsers.add_parser('fc1', help='Function 1')
    parser_f1.set_defaults(func=function_1)

    parser_f2 = subparsers.add_parser('fc2', help='Function 2')
    parser_f2.set_defaults(func=function_2)

    parser_f3 = subparsers.add_parser('fc3', help='Function 3')
    parser_f3.add_argument("pass", help="function 3 argument")
    parser_f3.set_defaults(func=function_3)
        
    if len(sys.argv) <= 1:
        sys.argv.append('--help')

    options = parser.parse_args()
    options.func()

Error

usage: argtest.py [-h] {fc1,fc2,fc3} ...
argtest.py: error: unrecognized arguments: --arg

Upvotes: 0

Views: 123

Answers (2)

Brenden
Brenden

Reputation: 113

I don't suggest doing it this way, I'd personally suggest just using click instead, but this is one method for doing it I guess...

import sys
from argparse import ArgumentParser


def parse_args():
    parser = ArgumentParser()
    parser.add_argument(
        "-f", "--function", type=str, help="name of the function to call", default="echo"
    )
    parser.add_argument("func_args", nargs="*")
    return parser.parse_args(args=None if sys.argv[1:] else ["--help"])


def echo(*args):
    print(' '.join(*args))


if __name__ == "__main__":
    args = parse_args()
    eval(f"{args.function}({args.func_args})")

This approach feels fragile and wrong to me, but I believe this is line with the behavior you're asking for.

Upvotes: 0

larsks
larsks

Reputation: 311605

First, your pass option is only available to the fc3 subparser, so rather than python script.py --pass test, you would want:

python script.py fc3 --pass test

But you've defined a positional argument, not a command line option. You need to either call your script like this:

python script.py fc3 test

Or you need to fix your code:

parser_f3.add_argument('--pass', help='function 3 argument')

That would allow you run python script.py fc3 --pass test.


There are still additional problems with the code; your function3 function requires an argument, but you're calling options.func() with no arguments, which will result in a TypeError exception.

Upvotes: 1

Related Questions