Carlos Carvalho
Carlos Carvalho

Reputation: 107

how handle sys.argv if null argument is given

I've this issue with this condition using sys.argv inside a script.

The script includes several functions to classify, build and transform a dataset, no big deal.

In the beginning of the script I assign external arguments to 2 or 3 variables depending on the arguments.

if len(sys.argv) > 2:
    nfcv=sys.argv[1]
    pgrid = [int(x) for x in sys.argv[2].split(",")]
    refit =  sys.argv[3]
else:
    nfcv=sys.argv[1]
    pgrid = [int(x) for x in sys.argv[2].split(",")]
    refit =  ""

Below the command line to run the script with all 3 arg's.

OC_run_eval_ML.py 5 "2,4,6,8,10,12,14" y

During script execution I want to fit my classifier below only if the 3 argument = "y", if empty then pass

Below what I did

def fit(X,y):
    clf.fit(X, y)

if refit == "y" :
    fit(X_train_std,y_train)
else: pass

Without the 3rd argument (which mean I don't want to "fit" my model)

OC_run_eval_ML.py 5 "2,4,6,8,10,12,14"

I get the following error message :

Traceback (most recent call last):
  File "OC_run_eval_ML.py", line 25, in <module>
    refit =  sys.argv[3]
IndexError: list index out of range

It seems is not accepting the condition : "len(sys.argv) > 2:"

Help is welcome.

Thank you in advance.

Rgds

Upvotes: 1

Views: 2796

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121484

The sys.argv list always contains the script name as the first argument, so when you have 3 command-line arguments, the length of sys.argv will be 4 elements. len(sys.argv) > 2 is true if there are only 3 elements too.

Test for 3 or more:

if len(sys.argv) > 3:
    nfcv=sys.argv[1]
    pgrid = [int(x) for x in sys.argv[2].split(",")]
    refit =  sys.argv[3]
else:
    nfcv=sys.argv[1]
    pgrid = [int(x) for x in sys.argv[2].split(",")]
    refit =  ""

You can simplify this to:

nfcv = sys.argv[1]
pgrid = [int(x) for x in sys.argv[2].split(",")]
if len(sys.argv) > 3:
    refit =  sys.argv[3]
else:
    refit =  ""

Personally, I'd use the argparse library to do this work for you, or (for more complex projects) with click.

Argparse example:

import argparse

parser = argparse.ArgumentParser(description='Classify, build and transform a dataset')
parser.add_argument("nfcv", help="The NFCV argument...")
parser.add_argument("pgrid", 
    help="Comma-separated pgrid values",
    type=lambda v: [int(x) for x in v.split(",")]
)
parser.add_argument("refit", nargs="?", default="", help="The refit argument...")

args = parser.parse_args()

then use args.nfcv, args.pgrid and args.refit in your code.

Demo:

$ cat demo.py
import argparse

parser = argparse.ArgumentParser(description='Classify, build and transform a dataset')
parser.add_argument("nfcv", help="The NFCV argument...")
parser.add_argument("pgrid",
    help="Comma-separated pgrid values",
    type=lambda v: [int(x) for x in v.split(",")]
)
parser.add_argument("refit", nargs="?", default="", help="The refit argument...")

args = parser.parse_args()

print(f"NFCV:  {args.nfcv!r}")
print(f"prid:  {args.pgrid!r}")
print(f"refit: {args.refit!r}")

$ python3 demo.py --help
usage: demo.py [-h] nfcv pgrid [refit]

Classify, build and transform a dataset

positional arguments:
  nfcv        The NFCV argument...
  pgrid       Comma-separated pgrid values
  refit       The refit argument...

optional arguments:
  -h, --help  show this help message and exit
$ python3 demo.py foo 42,81,117
NFCV:  'foo'
prid:  [42, 81, 117]
refit: ''
$ python3 demo.py foo 42,81,117 y
NFCV:  'foo'
prid:  [42, 81, 117]
refit: 'y'

Note that if refit is meant to be a switch, then just use a store_true action and make it a -r/--refit command line argument:

parser.add_argument(
    '-r', '--refit', action='store_true', default=False,
    help="Enable refit"
)

instead of the parser.add_argument('refit', ...) line. In that case args.refit is a boolean that defaults to False and is -r or --refit is used on the command line is set to True. Then just use if args.refit: to test for it.

The demo with that change then looks like this:

$ python3 demo.py --help
usage: demo.py [-h] [-r] nfcv pgrid

Classify, build and transform a dataset

positional arguments:
  nfcv         The NFCV argument...
  pgrid        Comma-separated pgrid values

optional arguments:
  -h, --help   show this help message and exit
  -r, --refit  Enable refit
$ python3 demo.py foo 42,81,117
NFCV:  'foo'
prid:  [42, 81, 117]
refit: False
$ python3 demo.py foo 42,81,117 --refit
NFCV:  'foo'
prid:  [42, 81, 117]
refit: True

Upvotes: 0

John Burger
John Burger

Reputation: 3672

  • argv[0] is always the name of the program;
  • argv[1] is the first argument;
  • argv[2] is the second argument; etc.

So if you want to confirm how many arguments there are, you need to remember that the "first" argument is actually the name of the program!

You want len(sys.argv)>3, not 2

Upvotes: 1

Related Questions