When you give a function a set of needed arguments or assign argv, the code demands that you give the correct number of args or it goes on to give, "expected number of things to unpack from a tuple is wrong", sorts of errors.
But I use scripts everyday that are very dynamic in how specifically the arguments can be given and in which types orders, etc.
I eventually imagine making scripts with a --help switch that list all the possible argv and options you can add, but for now as I am beginning, lets keep it very, somewhat simple:
I want the following to not raise error and to not EXPECT arguments to be given but to take them when they are there:
#!/usr/bin/env python3
from sys import argv
script, verbose_option, user_input = argv
if "verbose" in verbose_option:
verbose_option = True
else:
verbose_option = False
x = value
if verbose_option == True:
print("var x is set to value...")
else:
pass
if user_input == True: # if true, the var contains any value, correct?
print(user_input)
else:
print("user_input not given but, ... no problem!")
user_input = input("> ") # or maybe it has a default value that can be changed from argv
if verbose_option == True:
print("Would I really need this conditional on every line I left a verbose explanation on?")
else:
pass
Somehow it has to know that user_input is not intended as verbose just because verbose isn't there, so... maybe a conditional branch that tests the len()
of the tuple of arguments and figures, "well, that must be this and not that based on that number. OR.... is that overly complex and there is a better way?
This is a less important: how messy a verbose option must make the code if there isn't a better way than I imagined in the example code, but that's a bonus question. I want to not error and have default values for things or means of getting the data if not given as argv despite being able to be taken as argv.
You can iterate over the arguments that way:
def handle_arguments(argv):
env = {'user_input': []}
for arg in argv:
if arg in ['-v', '--verbose']
env['verbose'] = True
elif arg in ['-h', '--help']
display_help()
sys.exit(0)
else
env['user_input'] += [arg]
if length(env['user_input']) == 0
env['user_input'] = input('> ')
else
env['user_input'].join(' ')
return env
there you've got a function that takes arguments and returns a well formed env
variable.
So then you can pass sys.argv to handle_arguments by removing the useless sys.argv[0] (useless in this context)
import sys
if __name__ == "__main__":
env = handle_arguments(sys.argv[1:])
do_stuff(**env)
where stuff is either a function with the following prototype:
def do_stuff(user_input='', verbose=False):
or you can make it take any argument:
def do_stuff(**kwargs):
That being said, it's more or less the basic inner working of an argument parsing library. And to make it right, expectable by CLI users, you'd better use one, like Click, argparse or my personal favourite docopt.