tags:

views:

475

answers:

4

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] 
+7  A: 

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].

Thomas Wouters
+4  A: 

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.

David Zaslavsky
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.
Thomas Wouters
Thank you, knowing that the first element is the name of the program goes a long way in helping understand this!
Fred Gerbig
@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).
David Zaslavsky
+1  A: 

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, let's just shorten this 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?
wescpy
Thank you for the very clear explanation.
Fred Gerbig
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!
wescpy
A: 

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()
Fred Gerbig
Yes, the crash on your first version was probably because of using undefined labels fname and lname.
Van Gale
I am not clear on the undefined labels... how are they different from the name label? Is not name also undefined?
Fred Gerbig
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).
Van Gale
With no arguments I get:print 'Hello', fname, lnameUnboundLocalError: local variable 'fname' referenced before assignment______________With one argument I get:lname = sys.argv[2]IndexError: list index out of rangeI think I get it.... need to get back to the books and I am sure it will make sense.
Fred Gerbig