Checking if sys.argv[x] is defined

Question:

What would be the best way to check if a variable was passed along for the script:

try:
    sys.argv[1]
except NameError:
    startingpoint = 'blah'
else:
    startingpoint = sys.argv[1]
Asked By: Cmag

||

Answers:

Check the length of sys.argv:

if len(sys.argv) > 1:
    blah = sys.argv[1]
else:
    blah = 'blah'

Some people prefer the exception-based approach you’ve suggested (eg, try: blah = sys.argv[1]; except IndexError: blah = 'blah'), but I don’t like it as much because it doesn’t “scale” nearly as nicely (eg, when you want to accept two or three arguments) and it can potentially hide errors (eg, if you used blah = foo(sys.argv[1]), but foo(...) raised an IndexError, that IndexError would be ignored).

Answered By: David Wolever

It’s an ordinary Python list. The exception that you would catch for this is IndexError, but you’re better off just checking the length instead.

if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]
else:
  startingpoint = 'blah'
Answered By: Richard Barrell

Another way I haven’t seen listed yet is to set your sentinel value ahead of time. This method takes advantage of Python’s lazy evaluation, in which you don’t always have to provide an else statement. Example:

startingpoint = 'blah'
if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]

Or if you’re going syntax CRAZY you could use Python’s ternary operator:

startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'
Answered By: jathanism

In the end, the difference between try, except and testing len(sys.argv) isn’t all that significant. They’re both a bit hackish compared to argparse.

This occurs to me, though — as a sort of low-budget argparse:

arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))

You could even use it to generate a namedtuple with values that default to None — all in four lines!

Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))

In case you’re not familiar with namedtuple, it’s just a tuple that acts like an object, allowing you to access its values using tup.attribute syntax instead of tup[0] syntax.

So the first line creates a new namedtuple type with values for each of the values in arg_names. The second line passes the values from the args dictionary, using get to return a default value when the given argument name doesn’t have an associated value in the dictionary.

Answered By: senderle

I use this – it never fails:

startingpoint = 'blah'
if sys.argv[1:]:
   startingpoint = sys.argv[1]
Answered By: anatoly techtonik

You can simply append the value of argv[1] to argv and then check if argv[1] doesn’t equal the string you inputted Example:

from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
            print(argv[1])
Answered By: Hassan Abdul-Kareem

Pretty close to what the originator was trying to do. Here is a function I use:

def get_arg(index):
    try:
        sys.argv[index]
    except IndexError:
        return ''
    else:
        return sys.argv[index]

So a usage would be something like:

if __name__ == "__main__":
    banner(get_arg(1),get_arg(2))
Answered By: J. Barber

A solution working with map built-in fonction !

arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}

Then you just have to call your parameters like this:

if args['operation'] == "division":
    if not args['parameter']:
        ...
    if args['parameter'] == "euclidian":
        ...
Answered By: Guillaume Hillion
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.