0

Background

I am trying to write a python script that contains multiple functions like this:

 import sys
 def util1(x, y):
     assert(x is not None)
     assert(y is not None)
     #does something

 def util2(x, y):
     assert(x is not None)
     assert(y is not None)
     #does something

 def util3(x, y):
     assert(x is not None)
     assert(y is not None)
     #does something

I need to be able to call any method command line:

 python3 myscript.py util1 arg1 arg2

or

 python3 myscript.py util3 arg1 arg2

Problem

I don't know the proper way to grab the command line args and pass them to the methods. I found a way to grab the first arg... but I would like a way to say "pass all arg to function x" if this is possible.

What I've tried So far

So far, I at the bottom of my script, I added the following logic:

 if __name__ == '__main__':
     globals()[sys.argv[1]]()

and so now, when I try to run my script, I get the following response:

 lab-1:/var/www/localhost/htdocs/widgets# python3 myscript.py utils1 1 99999
 Traceback (most recent call last):
 File "myscript.py", line 62, in <module>
    globals()[sys.argv[1]]()
 TypeError: util1() missing 2 required positional arguments: 'x' and 'y'

I've also tried the following:

     globals()[*sys.argv[1:]]()
     globals()[*sys.argv[1]:[2]]()

But that doesn't work. I'm getting errors like "TypeError: unhashable type: 'list'

If you can point me in the right direction, I'd appreciate it. Thanks.

EDIT 1

Based on the recommendation here to review a similar post, I changed my logic to include the argparse library.  So now I have the following: 

parser = argparse.ArgumentParser(description='This is the description of my program')
parser.add_argument('-lc','--lower_create', type=int, help='lower range value for util1')
parser.add_argument('-uc','--upper_create', type=int, help='upper range value for util1')
parser.add_argument('-lr','--lower_reserve', type=int, help='lower range value for util3')
parser.add_argument('-ur','--upper_reserve', type=int, help='upper range value for util3')

args = parser.parse_args()
#if __name__ == '__main__':
#    globals()[sys.argv[1]](sys.argv[2], sys.argv[3])

What's not clear is how I "link" these arguments with a specific function. So let's say I need -lc and -uc for util1. How can I make that association? and then for example associate -lr and -ur with util3? Thank you

dot
  • 14,928
  • 41
  • 110
  • 218
  • 5
    Possible duplicate of [How to read/process command line arguments?](https://stackoverflow.com/questions/1009860/how-to-read-process-command-line-arguments) – buran Jan 09 '19 at 14:19

3 Answers3

0

You need to pass the arguments to the function when you call it. The naive way to do this would be like this: globals()[sys.argv[1]](sys.argv[2], sys.argv[3]) although you'll probably want to do some extra checking to make sure the arguments exist, as well as the function being called.

Marcus
  • 3,216
  • 2
  • 22
  • 22
0

You could do this quite neatly with click, e.g.

@click.command()
@click.argument('x')
@click.argument('y')
def util1(x, y):
     #does something

You can also use varargs, so you don't have to specify every argument:

@click.command()
@click.argument('args', nargs=-1)
def util2(args):
    #does something, args is a list

Click also supports different arguments types, validation, etc.

BlackBear
  • 22,411
  • 10
  • 48
  • 86
0

That is a nice question. Try like this.

import sys
def util1(x, y):
    print('This is "util1" with the following arguments: "'+x+'" and "'+y+'"')
    #does something
def util2(x, y):
    print('This is "util2" with the following arguments: "'+x+'" and "'+y+'"')
    #does something

def util3(x, y):
    print('This is "util3" with the following arguments: "'+x+'" and "'+y+'"')
    #does something

locals()[sys.argv[1]](sys.argv[2] , sys.argv[3])

Then calling it like this, works great for me. Just tried it on my test machine.

python file.py util1 arg1 arg2
Paddy
  • 123
  • 7