29

In the below code I understand that sys.argv uses lists, however I am not clear on how the index's are used here.

def main(): if len(sys.argv) >= 2: name = sys.argv[1] else: name = 'World' print 'Hello', name if __name__ == '__main__': main() 

If I change

name = sys.argv[1] 

to

name = sys.argv[0] 

and type something for an argument it returns:

Hello C:\Documents and Settings\fred\My Documents\Downloads\google-python-exercises \google-python-exercises\hello.py 

Which kind of make sense.

Can someone explain how the 2 is used here:

if len(sys.argv) >= 2: 

And how the 1 is used here:

name = sys.argv[1] 

5 Answers 5

48

Let's say on the command-line you have:

C:\> C:\Documents and Settings\fred\My Documents\Downloads\google-python-exercises \google-python-exercises\hello.py John 

To make it easier to read, shorten it to:

C:\> hello.py John 

argv represents all the items that come along via the command-line input, but counting starts at zero (0) not one (1): in this case, "hello.py" is element 0, "John" is element 1

In other words, sys.argv[0] == 'hello.py' and sys.argv[1] == 'John' ... but look, how many elements is this? 2, right! so even though the numbers are 0 and 1, there are 2 elements here.

len(sys.argv) >= 2 just checks whether you entered at least two elements. in this case, we entered exactly 2.

Now let's translate your code into English:

define main() function: if there are at least 2 elements on the cmd-line: set 'name' to the second element located at index 1, e.g., John otherwise there is only 1 element... the program name, e.g., hello.py: set 'name' to "World" (since we did not get any useful user input) display 'Hello' followed by whatever i assigned to 'name' 

So what does this mean? It means that if you enter:

  • "hello.py", the code outputs "Hello World" because you didn't give a name
  • "hello.py John", the code outputs "Hello John" because you did
  • "hello.py John Paul", the code still outputs "Hello John" because it does not save nor use sys.argv[2], which was "Paul" -- can you see in this case that len(sys.argv) == 3 because there are 3 elements in the sys.argv list?
Sign up to request clarification or add additional context in comments.

3 Comments

yvw! i saw that others' already answered it pretty well and i wanted alternative that focused more on a pure "English translation" of the code, if there's such a thing. cheers!
You can also start your loop for i in range(1, len(sys.argv)-1): then get your value with sys.argv[i] if you need to know the position as well as the value.
While you could do that, use of "len()-1" is atypical Python even though it's a common pattern in other languages; it is more idiomatic Python to use enumerate() if both the index and the value are desired. This comment also does not address the OP question, which asks how indexes work -- they did not ask how one would query for a specific value or its position.
12

sys.argv is the list of arguments passed to the Python program. The first argument, sys.argv[0], is actually the name of the program as it was invoked. That's not a Python thing, but how most operating systems work. The reason sys.argv[0] exists is so you can change your program's behaviour depending on how it was invoked. sys.argv[1] is thus the first argument you actually pass to the program.

Because lists (like most sequences) in Python start indexing at 0, and because indexing past the end of the list is an error, you need to check if the list has length 2 or longer before you can access sys.argv[1].

Comments

6

In a nutshell, sys.argv is a list of the words that appear in the command used to run the program. The first word (first element of the list) is the name of the program, and the rest of the elements of the list are any arguments provided. In most computer languages (including Python), lists are indexed from zero, meaning that the first element in the list (in this case, the program name) is sys.argv[0], and the second element (first argument, if there is one) is sys.argv[1], etc.

The test len(sys.argv) >= 2 simply checks wither the list has a length greater than or equal to 2, which will be the case if there was at least one argument provided to the program.

3 Comments

You seem to be using array to mean list a few times. They're different things. sys.argv is a list, as you mention in the first sentence.
Thank you, knowing that the first element is the name of the program goes a long way in helping understand this!
@Thomas: good point, I'll fix that... I tend to use the terms interchangeably since Python's lists often serve the same function as C's arrays (and in this case the distinction isn't particularly important).
5

So if I wanted to return a first name and last name like: Hello Fred Gerbig I would use the code below, this code works but is it actually the most correct way to do it?

import sys def main(): if len(sys.argv) >= 2: fname = sys.argv[1] lname = sys.argv[2] else: name = 'World' print 'Hello', fname, lname if __name__ == '__main__': main() 

Edit: Found that the above code works with 2 arguments but crashes with 1. Tried to set len to 3 but that did nothing, still crashes (re-read the other answers and now understand why the 3 did nothing). How do I bypass the arguments if only one is entered? Or how would error checking look that returned "You must enter 2 arguments"?

Edit 2: Got it figured out:

import sys def main(): if len(sys.argv) >= 2: name = sys.argv[1] + " " + sys.argv[2] else: name = 'World' print 'Hello', name if __name__ == '__main__': main() 

4 Comments

Yes, the crash on your first version was probably because of using undefined labels fname and lname.
I am not clear on the undefined labels... how are they different from the name label? Is not name also undefined?
In the first version, if there are less than 2 command line arguments, the print statement will break because 'fname' and 'lname' are undefined (i.e. used before assignment).
With no arguments I get: print 'Hello', fname, lname UnboundLocalError: local variable 'fname' referenced before assignment______________ With one argument I get: lname = sys.argv[2] IndexError: list index out of range I think I get it.... need to get back to the books and I am sure it will make sense.
2

As explained in the different asnwers already, sys.argv contains the command line arguments that called your Python script.

However, Python comes with libraries that help you parse command line arguments very easily. Namely, the new standard argparse. Using argparse would spare you the need to write a lot of boilerplate code.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.