What's the best way to generate random strings of a specific length in Python?

PythonRandom

Python Problem Overview


For a project, I need a method of creating thousands of random strings while keeping collisions low. I'm looking for them to be only 12 characters long and uppercase only. Any suggestions?

Python Solutions


Solution 1 - Python

CODE:

from random import choice
from string import ascii_uppercase

print(''.join(choice(ascii_uppercase) for i in range(12)))

OUTPUT:

5 examples:

QPUPZVVHUNSN
EFJACZEBYQEB
QBQJJEEOYTZY
EOJUSUEAJEEK
QWRWLIWDTDBD

EDIT:

If you need only digits, use the digits constant instead of the ascii_uppercase one from the string module.

3 examples:

229945986931
867348810313
618228923380

Solution 2 - Python

By Django, you can use get_random_string function in django.utils.crypto module.

get_random_string(length=12,
    allowed_chars=u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
	Returns a securely generated random string.
	
	The default length of 12 with the a-z, A-Z, 0-9 character set returns
	a 71-bit value. log_2((26+26+10)^12) =~ 71 bits

Example:

get_random_string()
u'ngccjtxvvmr9'

get_random_string(4, allowed_chars='bqDE56')
u'DDD6'

But if you don't want to have Django, here is independent code of it:

Code:

import random
import hashlib
import time

SECRET_KEY = 'PUT A RANDOM KEY WITH 50 CHARACTERS LENGTH HERE !!'

try:
    random = random.SystemRandom()
    using_sysrandom = True
except NotImplementedError:
    import warnings
    warnings.warn('A secure pseudo-random number generator is not available '
                  'on your system. Falling back to Mersenne Twister.')
    using_sysrandom = False


def get_random_string(length=12,
                      allowed_chars='abcdefghijklmnopqrstuvwxyz'
                                    'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
    """
    Returns a securely generated random string.

    The default length of 12 with the a-z, A-Z, 0-9 character set returns
    a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
    """
    if not using_sysrandom:
        # This is ugly, and a hack, but it makes things better than
        # the alternative of predictability. This re-seeds the PRNG
        # using a value that is hard for an attacker to predict, every
        # time a random string is required. This may change the
        # properties of the chosen random sequence slightly, but this
        # is better than absolute predictability.
        random.seed(
            hashlib.sha256(
                ("%s%s%s" % (
                    random.getstate(),
                    time.time(),
                    SECRET_KEY)).encode('utf-8')
            ).digest())
    return ''.join(random.choice(allowed_chars) for i in range(length))

Solution 3 - Python

Could make a generator:

from string import ascii_uppercase
import random
from itertools import islice

def random_chars(size, chars=ascii_uppercase):
	selection = iter(lambda: random.choice(chars), object())
	while True:
		yield ''.join(islice(selection, size))

random_gen = random_chars(12)
print next(random_gen)
# LEQIITOSJZOQ
print next(random_gen)
# PXUYJTOTHWPJ

Then just pull from the generator when they're needed... Either using next(random_gen) when you need them, or use random_200 = list(islice(random_gen, 200)) for instance...

Solution 4 - Python

For cryptographically strong pseudo-random bytes you might use the pyOpenSSL wrapper around OpenSSL.

It provides the bytes function to gather a pseudo-random sequences of bytes.

from OpenSSL import rand

b = rand.bytes(7)

BTW, 12 uppercase letters is a little bit more that 56 bits of entropy. You will only to have to read 7 bytes.

Solution 5 - Python

This function generates random string of UPPERCASE letters with the specified length,

eg: length = 6, will generate the following random sequence pattern

> YLNYVQ

    import random as r

    def generate_random_string(length):
        random_string = ''
        random_str_seq = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        for i in range(0,length):
            if i % length == 0 and i != 0:
                random_string += '-'
            random_string += str(random_str_seq[r.randint(0, len(random_str_seq) - 1)])
        return random_string

Solution 6 - Python

#!/bin/python3
import random
import string
def f(n: int) -> str:
        bytes(random.choices(string.ascii_uppercase.encode('ascii'),k=n)).decode('ascii')

run faster for very big n. avoid str concatenate.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrandonView Question on Stackoverflow
Solution 1 - PythonPeter VaroView Answer on Stackoverflow
Solution 2 - PythonOmid RahaView Answer on Stackoverflow
Solution 3 - PythonJon ClementsView Answer on Stackoverflow
Solution 4 - PythonSylvain LerouxView Answer on Stackoverflow
Solution 5 - PythonManoj SelvinView Answer on Stackoverflow
Solution 6 - Python把友情留在无盐View Answer on Stackoverflow