Random strings

import matplotlib.pyplot as plt
import random
import string

To generate random strings, we’ll need to utitize Python’s string and random modules together. The string module provides constants such as ASCII letters (ascii_letters), digits, and punctuations.

string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.digits
'0123456789'
string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

Say we need to generate a password of a specified length using a random combination of lowercase ascii characters, digits, and punctuation. We can use either choices() or sample() to grab our random characters.

The following function takes a parameter k which specifies the length of the string to be generated (by default 12). It then stores a set of available characters to choose from in the char_pool variable. Depending on whether we want duplicates or not, the function can use sample() or choices() to take samples from the characters in char_pool. This function needs to return a string, so since both sample() and choices() return an array, then we use the join() function to glue the values together into a single string.

def generate_random_str(k=12):
    char_pool = set(string.ascii_letters + string.digits + string.punctuation)
    
    random_str = random.sample(char_pool, k)
    # random_str = random.choices(char_pool, k=k)  # alternatively use choices() to allow duplicate chars

    return ''.join(random_str)
generate_random_str()
'Y}#KuvV8?/ew'

Then similarly with numbers, we can use list comprehension to generate n number of random strings.

# Generate 5 random strings
[generate_random_str() for _ in range(5)]
['%>&,Ti!KqR7W',
 ';1(P[,V/!~Ey',
 'vWxRJDq<Z`.:',
 'g^,8L6w(m!_n',
 'i[7~L6-J%SmN']

Cryptographically safe random strings

Sometimes it’s not enough to generate random strings using pseudo-random functions, which output numbers deterministically. Some systems require random strings like passwords to be generated in a secure way (i.e., the function that generated them would be difficult to impossible to infer). We can quickly whip up cryptographically secure strings using Python’s secrets module.

import secrets
char_pool = string.ascii_letters + string.digits + string.punctuation

''.join(secrets.choice(char_pool) for _ in range(12))
'~{"Yp"t$uq">'

We can use this to generate real passwords that follow some security rules, like the one below where the password needs to have at least one digit, at least 2 uppercase letters, and at least 3 lowercase characters.

# Keep generating strings until one satisfies all of the constraints
while True:
    secret = ''.join(secrets.choice(char_pool) for _ in range(12))
    if (any(c.isdigit() for c in secret)) and \
       (sum(c.isupper() for c in secret) >= 2) and \
       (sum(c.islower() for c in secret) >= 3):
        print(secret)
        break
j33Sm2<kCHl"