map() lambda() unsupported operand only with python 2.7.6

119 Views Asked by At

I am asking for help in last resort, I have a problem with my code that is driving me crazy. I work with both Python 2.7.6 and Python 3.4.3 on Ubuntu 14.04 with the following very simple part of code that I took from there password generator urandom

import os


def random_password(length=20, symbols='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@$^_+&'):
    password = []
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
        password.append(symbols[i])
    return ''.join(password)

random_password()

password = random_password()

print(password)

This part of code works with python 3.4.3. but randomly give the following error every 2 or 3 run:

Traceback (most recent call last):
  File "/home/jsmith/Documents/PythonProjects/MainFile", line 12, in <module>
    IotaSeed = Gen_Seed()
  File "/home/jsmith/Documents/PythonProjects/MainFile", line 7, in Gen_Seed
    IotaSeed.append(symbols[i])
IndexError: string index out of range

And with Python 2.7.6, it doesn't work at all and give the following error :

Traceback (most recent call last):
  File "PWDGEN.py", line 10, in <module>
    random_password()
  File "PWDGEN.py", line 6, in random_password
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
  File "PWDGEN.py", line 6, in <lambda>
    for i in map(lambda x: int(len(symbols)*x/255.0), os.urandom(length)):
TypeError: unsupported operand type(s) for /: 'str' and 'float'

I understand how lambda and map works but I just can't find a solution and I can't switch to python 3.4.3 because I coded my main program with 2.7.

What can I do to make it works under python 2.7 and avoid the "string index out of range" error seen in 3.4.3?

Thanks, PGriffin.

1

There are 1 best solutions below

0
Ry- On
int(len(symbols)*x/255.0)

can result in len(symbols) when x == 255. To fix that, you could divide by 256 instead. This won’t give evenly-distributed random characters, though, which is undesirable for password generation. Use SystemRandom instead:

import string
from random import SystemRandom


ALPHANUMERICS = string.ascii_letters + string.digits


def random_password(length=20, symbols=ALPHANUMERICS + '@$^_+&'):
    rng = SystemRandom()
    return ''.join(rng.choice(symbols) for _ in range(length))

Compare how often each character appears in a password before:

histogram not characteristic of a uniform distribution

and after:

histogram characteristic of a uniform distribution