I have gone through the sys
documentation, however there is something that is still unclear to me. I have looked for some similar question on stackoverflow, but I haven't find anything useful (clearly any reference is appreciated!).
I want to create a script - say foo.py
- in which I want pass from 3 to 6 arguments:
$ python foo.py arg1 arg2 arg3
The first 3 arguments must be given in any case; the last 3 arguments are used in a function that have default argument values if nothing is passed.
The question is how do I do this? So far I was thinking to write something like the following foo.py
(this is an easy example set only for the purpose of having something concrete in support of my question):
import sys
def example(credit_mom, credit_dad, debt_mom, debt_dad = 1000,
salary = 2000, bonus = 0):
total_gain = salary + credit_dad + credit_mom + bonus
total_loss = debt_dad + debt_mom
return total_gain - total_loss
if __name__ == '__main__':
if len(sys.argv) < 4:
sys.exit('Need at least 3 arguments. The order is as follows:\n\
1.credit_mom;\n\
2.credit_dad;\n\
3.debt_mom;\n\
4.others')
else:
sys.exit(example(sys.argv[1],
sys.argv[2],
sys.argv[3],
sys.argv[4],
sys.argv[5],
sys.argv[6]))
If I run this script I clearly get an IndexError
exception:
$ python foo.py 110 110 220
Traceback (most recent call last):
File "foo.py", line 19, in <module>
sys.argv[4],
IndexError: list index out of range
I suggest you use argparse (and here is the tutorial ). Saves you having to manually check for the existence of parameters. Moreover argparse gives you the --help
argument as a freebie, which will read the help=""
string defined for each argument, if provided.
In your case you have three mandatory (positional) argument and three optional ones. A sample argparse code would look like this:
#!/usr/bin/python
# coding: utf-8
import argparse
def parseArguments():
# Create argument parser
parser = argparse.ArgumentParser()
# Positional mandatory arguments
parser.add_argument("creditMom", help="Credit mom.", type=float)
parser.add_argument("creditDad", help="Credit dad.", type=float)
parser.add_argument("debtMom", help="Debt mom.", type=float)
# Optional arguments
parser.add_argument("-dD", "--debtDad", help="Debt dad.", type=float, default=1000.)
parser.add_argument("-s", "--salary", help="Debt dad.", type=float, default=2000.)
parser.add_argument("-b", "--bonus", help="Debt dad.", type=float, default=0.)
# Print version
parser.add_argument("--version", action="version", version='%(prog)s - Version 1.0')
# Parse arguments
args = parser.parse_args()
return args
def example(credit_mom, credit_dad, debt_mom, debt_dad = 1000, salary = 2000, bonus = 0):
total_gain = salary + credit_dad + credit_mom + bonus
total_loss = debt_dad + debt_mom
return total_gain - total_loss
if __name__ == '__main__':
# Parse the arguments
args = parseArguments()
# Raw print arguments
print("You are running the script with arguments: ")
for a in args.__dict__:
print(str(a) + ": " + str(args.__dict__[a]))
# Run function
print(example(args.creditMom, args.creditDad, args.debtMom, args.debtDad, args.salary, args.bonus))
While I endorse the argparse
approach, here's a quick and dirty approach:
arg1, arg2, arg3 = [None, False, []]
if sys.argv[1:]: # test if there are atleast 1 argument (beyond [0])
arg1 = sys.argv[1]
if sys.argv[2:]:
arg2 = sys.argv[2] # careful 'True' is a string, not a boolean
arg3 = sys.argv[3:] # rest
Mostly I use this when I'm starting to add argument parsing to a script, and my choices of arguments hasn't matured. It's more suited to 'positionals' than 'optionals' (to use argparse terminology).
Other than using argparse
(which I do recommend), this can be solved by slicing and expanding:
sys.exit(example(*sys.argv[1:7]))
The slice will only contain elements that actually exist, even if there aren't enough to fulfill the size of slice requested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With