How to Generate a Random String in Python?

Rate this post

Problem Formulation

You are tasked with writing Python code to generate a random string.  The string should contain any of the printable characters on your keyboard.  Letters, numbers, and punctuation marks are valid, and we’ll leave out any whitespace characters.

What’s the best way to solve this in Python?

Method 1: List Comprehension and random.randint()

Since Python has built-in functions to convert ASCII/Unicode, then we will take advantage of that.  Here’s a screenshot of the chart taken from asciitable.com

Note the column labeled “Dec” is for decimal, and the corresponding characters are in the “Chr” column. Therefore, decimal 33 is equivalent to the exclamation point '!', and the lower case letter 'x' is equivalent to 120.   Let’s prove this with the Python function chr() on decimal 33. And converting from character to decimal using ord(), let’s check lowercase 'x'.

>>> print(chr(33))
!
>>> print(ord('x'))
120
>>>

Referring back to the chart, we should make note that all the letters, numbers, symbols, and punctuation are within decimal numbers 33 to 126.  With that in mind, we can specify to generate random numbers within this range and then convert that number to its corresponding character using the chr() function.

Here’s one of a few different ways to make a list of random numbers.

First, we’ll import the random module.  And let’s assume we need to generate a random string with a length of 10 characters. 

>>> import random
>>> length = 10
>>>

Next we’ll use list comprehension to make our list of random numbers.

>>> rand_num = [random.randint(33, 126) for _ in range(length)]
>>> print(rand_num)
[73, 62, 100, 107, 39, 68, 98, 65, 96, 125]
>>>

Now we need to convert our list of numbers to the corresponding character values.  I’ll use map() and specify chr as the function and rand_num as the iterable.  Don’t forget to pass that into a list() constructor.

>>> str_lst = list(map(chr, rand_num))
>>> print(str_lst)
['I', '>', 'd', 'k', "'", 'D', 'b', 'A', '`', '}']
>>>

And now we have a list of random characters!  The last step is to convert the list items to a string.

>>> rand_str = ''.join(str_lst)
>>> print(rand_str)
I>dk'DbA`}
>>>

And one of the great things I love about Python is that the above can be reduced to one line of code (besides the import line and length variable initialization to 10).

>>> ''.join(list(map(chr, [random.randint(33, 126) for _ in range(length)])))
'^Do!f@=;j$'
>>>

Method 2: random.choices and string.printable

If you do not want to use the ASCII/Unicode tables as a visual reference, then we can rely on Python’s “string” module which defines the following constants.  Here’s a screenshot from the Python docs.

These will be suitable for solving our problem of generating a random string.  For our purpose, we’ll use “string.printable”.  But since it includes whitespace characters, we’ll have to make sure those are omitted.

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

Above code showing list comprehension to populate the variable prnt_lst, as long as it’s not in “string.whitespace”. 

Now we can import the random module and use the choices() function passing in our prnt_list and specifying the size k.  This will generate a list of 10 random characters.  And the last step is to use ''.join() and assign it to the variable rnd_str.

>>> import random
>>> rnd_lst = random.choices(prnt_lst, k=10)
>>> print(rnd_lst)
["'", '{', '*', 'o', 'a', 'M', 'q', '[', 'E', '>']
>>> rnd_str = ''.join(rnd_lst)
>>> print(rnd_str)
'{*oaMq[E>
>>>

And if you’re interested in seeing the one-line solution (after importing string and random):

>>> print(''.join(random.choices([x for x in string.printable if x not in string.whitespace], k=10)))
}36.oPQV)i
>>>

Method 3: secrets.choice

In this third method, I will discuss generating a random string for use as a password

Python has a module called “secrets” which is intended for generating cryptographically strong random numbers.  This will be similar to Method 2 in that we will create a list of printable characters and exclude whitespaces. 

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

However we’ll use the secrets.choice() function in a generator expression to randomly choose the characters. 

>>> (secrets.choice(prnt_lst) for x in range(10))
<generator object <genexpr> at 0x7f2d8343aeb0>

Notice the interpreter has displayed the result as a generator object.  We’ll need to use ''.join() to see the results.

>>> ''.join((secrets.choice(prnt_lst) for x in range(10)))
'E,^a*OIb:s'

And finally here’s the one-liner. To increase security I have specified the password length to be 16 characters long.

>>> ''.join(secrets.choice([x for x in string.printable if x not in string.whitespace]) for x in range(16))
'uaJt}p7E?3yvGq%v'
>>>

Summary

Today we discussed some ways to generate a random string in Python. 

  • The first method involves a bit more effort on your part since you’ll have to refer to the ASCII table to see which characters correspond to the intended decimal range for your string. 
  • However, we saw in the second method the Python module “string” has some constants defined for all the printable characters.  Just remember to exclude the whitespaces! 
  • And lastly, I went over the Pythonic way to generate a random string for password use.

I hope you enjoyed reading this article as much as I enjoyed writing it.  Take care, and I look forward to sharing more one-liners with you in the next article.