0

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
3
  • show the full error message, including usage Commented Jan 6, 2023 at 15:08
  • sorry, one minute Commented Jan 6, 2023 at 16:03
  • Have you considered using click instead? click.palletsprojects.com/en/8.1.x Commented Jan 6, 2023 at 16:16

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

What constitutes a positional argument (name) or a command line option (flag) is highlighted in name or flags.
0

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.

Comments

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.