random.choice() returns same value at the same second, how does one avoid it?

Axel Ekeberg picture Axel Ekeberg · Sep 21, 2015 · Viewed 8.2k times · Source

I have been looking at similar questions regarding how to generate random numbers in python. Example: Similar Question - but i do not have the problem that the randomfunction returns same values every time.

My random generator works fine, the problem is that it returns the same value when calling the function at, what I think, the same second which is undesireable.

My code looks like this

def getRandomID():
    token = ''
    letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    for i in range(1,36):
        token = token + random.choice(letters)
    return token

As I mentioned this function returns different values when being called at on different times but returns the same value when calling the function at the same time. How do I avoid this problem?

I use this function in a back-end-server to generate unique IDs for users in front-end to insert in a database so I cannot control the time intervals when this happens. I must have random tokens to map the users in the database to be able to insert them correctly with queuenumbers in the database.

Answer

Martin Evans picture Martin Evans · Sep 21, 2015

You could possibly improve matters by using random.SystemRandom() as follows:

import random

sys_random = random.SystemRandom()

def getRandomID():
    token = ''
    letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    for i in range(1, 36):
        token = token + sys_random.choice(letters)
    return token

print(getRandomID())

This attempts to use the os.urandom() function which generates random numbers from sources provided by the operating system. The .choices() function could also be used to return a list of choices in a single call, avoiding the string concatenation:

import random

sys_random = random.SystemRandom()

def getRandomID():
    letters = "abcdefghiklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    return ''.join(sys_random.choices(letters, k=35))

print(getRandomID())