2

I'm new user of stackoverflow, besides I'm not an English guy, so I'm sorry for my english.

I was programming in python 'til I got a mistake tho I'm not able to figure out what's wrong...

#!/usr/bin/env python2.7

from random import choice
import sys

def help():
    print ("Please, you need to introduce a Int in this way: PWrand 10")

def PWrand(insert_by_user):
    chars = 'ABCDEFGHIJKLMNOPQRSTUWXYZabcdefghijklmnopqrstuwxyz0123456789!-_:.,;&)('

    for password in range(insert_by_user):
        sys.stdout.write(choice(chars))

 #Command Line

if __name__ == '__main__':

    if len(sys.argv) < 2 or len(sys.argv) > 2:
        help()

    elif (type(sys.argv[2]) != int):
        print("It need to be an Int!")

    else:
        insert_by_user = (sys.argv[2])
        print(PWrand(insert_by_user))

So, this is what I take.

Traceback (most recent call last):
  File "./passwordrandom.py", line 24, in <module>
    elif (type(sys.argv[2]) != int):
IndexError: list index out of range

Thank you all!

Sharki
  • 404
  • 4
  • 23
  • 3
    Numbering of list elements starts with 0, so for a list with two elements the elements have which numbers? – Michael Butscher Dec 06 '17 at 00:06
  • Oh... I thought it started in '2' 'cause it's the second argument you know? like, first one the python name, and second one the argument. Now I see, tho I found another issue, I can't read that like a int – Sharki Dec 06 '17 at 00:09
  • If a list has two items, the first is item 0 and the second is item 1. There is no item 2, and trying to access one is an error. – kindall Dec 06 '17 at 00:09
  • 2
    it won't be an int, it will be a string. use ```insert_by_user = int(sys.argv[1])``` and of course, if it is not the string representation of an int, like "b", be ready to catch that ValueError exception. – Martin Dec 06 '17 at 00:12
  • What is confusing to new programmers is using length on a sequence e.g. `len(sys.arg)` which in your testing will return 2, and an index on the sequence like `sys.argv[2]` which will give you the #3 item. There's some good reasons for zero-based indexing but mostly it causes confusion. Also, in your question you should show how you are calling the python script with your args to make it clear that you test with 2 args. – Davos Dec 06 '17 at 00:17

2 Answers2

1

You have two issues here. The first is that you're a little confused about list indexes. Lists in python are "zero-indexed" meaning that to get the first element of a list named L you need to do L[0]. Similarly, to get the second, like you need, you do L[1].

The other issue is that all elements from sys.argv are going to be strings, so checking the type won't work. You should try to cast the piece of user input as an int inside a try block and catch a ValueError. It'd look something like this:

if __name__ == '__main__':

    if len(sys.argv) < 2 or len(sys.argv) > 2:
        help()

    else:
        try:
            insert_by_user = int(sys.argv[1])
            print(PWrand(insert_by_user))
        except ValueError:
            print("It need to be an Int!")

The code inside the except ValueError: block will only be executed if the user's input cannot be properly cast to an integer.

wpercy
  • 9,636
  • 4
  • 33
  • 45
1

It's because the first if catch every list that has less than 2 elements or everything that has more than 2 elements, so the elif is catching everything that has exactly 2 elements, which will be stored in the position 0 and 1.

if len(sys.argv) is not 2:
    help()

else:
   user_input = sys.argv[1].decode()
   if not user_input.isnumeric():
      print("It need to be an Int!")
   else:
       user_input = int(user_input)

should fix it.

Shailyn Ortiz
  • 766
  • 4
  • 14
  • The sentence "is not" was so helpful, also makes sense xD! Thank you! – Sharki Dec 06 '17 at 00:25
  • Awesome, glad it could help. also notes that type() returns elements in the form of but it's the say that the types return. E.g: if you type "int" in the python interpreter it returns that's the pythonic way to check for a type of an object, variable, etc.. – Shailyn Ortiz Dec 06 '17 at 00:37
  • You should note that the `elif` branch can never return true. The argv list elements will always be strings and you should test its `int`ness by attempting a conversion to `int` and taking the throwing of an exception as a sign it failed. – Paul Rooney Dec 06 '17 at 00:49
  • @PaulRooney check it now ;) – Shailyn Ortiz Dec 06 '17 at 01:11
  • Its ok you needn't correct it. It's not part of the answer after all. Although I don't think you need the `decode` part. Its a string and you normally call decode on a `bytes` object. – Paul Rooney Dec 06 '17 at 02:26
  • What happens here is that isnumeric() is a method just for Unicodes. not strings so python 2.x won't know how to deal with it without the decode. if I were completely sure it is python 3, str.isnumeric() is valid as all characters are Unicode. – Shailyn Ortiz Dec 06 '17 at 02:34