Hello,

: Is there a less clunky way to do this?

Yes. There are probably many ways to do this, and this is just something I cooked up at a moment's notice in reply to your question, and probably could be significantly improved upon.

: def new_pass():

Your function takes no arguments. Maybe this is something to reconsider. Keep reading.

:     series = ['`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', 
'=', \
:               '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', 
'+', \
:               'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 
'\\', \
:               'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 
'|', \
:               'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", \
:               'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', \
:               'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', \
:               'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?']

So, if I were staring at my keyboard and starting to type in the characters (not a QWERTZ or AZERTY keyboard, it seems), I would ask myself the question--is there any module that has the complete set of characters that are available to me already, so I don't have to type them all in?

Indeed, there is? I found the module called 'string'. In that module, the following are available to you:

   ascii_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
   ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
   ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
   digits = '0123456789'
   hexdigits = '0123456789abcdefABCDEF'
   letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
   lowercase = 'abcdefghijklmnopqrstuvwxyz'
   octdigits = '01234567'
   printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU...
   punctuation = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
   uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
   whitespace = '\t\n\x0b\x0c\r '

OK, so because I believe in strong (or, at least, reasonably strong) passwords, I'll concatenate a few of these to make the set of characters that I would like to produce in a password. To me, the 'printable' set seems a bit, well, difficult for the person typing a password, so I'll stick with the following:

 validchars = string.ascii_letters + string.digits + string.punctuation
 series = list( validchars )

:     passwd = []
:     p = input("Enter the length you want your password to be: ")
:               # length of password

Maybe you could make the function 'new_pass' take as an argument the number of characters. That way, your function would not need to read input from anyplace else (the console). It could generate passwords of any length regardless of whether it was called from a CGI or command-line or even used from a bulk password generation system.

:     for i in range(p):
:         r = random.randint(0, 94)

Uh-oh! You had already counted and hard-coded the length of your variable 'series'! What happens if I want to add a few characters at the end? Like maybe the €, the £ or the ¥. I am currently obsessed with (con)currency.

If you were to let Python count the elements in your variable 'series', then you would not have to have counted all 94 elements yourself. So, think about why this might be better (more maintainable):

:     passwd = []
:     for i in range(p):
:         r = random.randint(0, len(series))
:         passwd.append(series[r]) # Append a random char from series[] to 
passwd

Now, in the (admittedly, revised loop, above), you generate a single random.randint() for each of the elements that you wish to extract. Chances are that somebody has already implemented a feature to do this sort of thing. Doesn't it seem like a pretty rational sort of thing to have a compute do? Select a bunch of elements randomly from an input set?

So, let's try this one of two different ways. Using option A, you can mix up your data and repeatedly pull out the same result for the N items:

 random.shuffle(series)
 ''.join(series[0:p])

In option B, you would get a different result each time:

 ''.join(random.sample(validchars,p))

So, I would rewrite your function to be (substituting 'charcount' for 'p'):

 #! /usr/bin/env python
import string
 import random
def new_pass(charcount):
     validchars = string.ascii_letters + string.digits + string.punctuation
     series = list( validchars )
     random.shuffle(series)
     print ''.join(series[0:charcount])
if __name__ == '__main__':
     new_pass(int(input("Enter the length you want your password to be: ")))

Two others have already suggested that you look at the string and random modules. Here's just one example of how you could use them together. Now, let's see what you do with MD5 and SHA. (You are looking at 'hashlib', correct?)

Good luck,

-Martin

--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to