Last updated: Apr 10, 2024
Reading timeยท6 min
Use the os.urandom()
method to generate random bytes of length N, e.g.
random_bytes = os.urandom(8)
.
The os.urandom()
method returns a bytestring of N random bytes suitable for
cryptographic use.
import os # โ create random bytestring that is 8 bytes long random_bytes = os.urandom(8) print(random_bytes) # ๐๏ธ b'\xd8\xa7\\\xe4~\xa2y\xe3' print(len(random_bytes)) # ๐๏ธ 8 # ------------------------------------------ # โ create random bytestring that is 16 bytes long random_bytes = os.urandom(16) # ๐๏ธ b'\xeb\xba^\x81\xe1\x00\xb9\x0c\x99\x1e\xe9\x86\x86\x0bl]' print(random_bytes) print(len(random_bytes)) # ๐๏ธ 16
The os.urandom() method
takes a size
argument and returns a cryptographically secure bytestring of
size
random bytes.
How the method is implemented depends on the underlying operating system.
If you need to generate a random bytearray
, pass the result of calling
os.urandom()
to the bytearray
class.
import os random_bytearray = bytearray(os.urandom(16)) # ๐๏ธ bytearray(b'\xe8\x87p\x11Y\xfd~\xff\xe6\xe1O\xbf\x06\xd8Om') print(random_bytearray)
The bytearray class copies the supplied binary data via the buffer protocol.
If you use a Python version newer than 3.9, you can use the newer
random.randbytes()
method.
The randbytes()
method generates n random bytes.
import random random_bytes = random.randbytes(8) print(random_bytes) # ๐๏ธ b'\xb0\x1c\x01:L\x95 \xa3' print(len(random_bytes)) # ๐๏ธ 8 # ------------------------------------------ random_bytes = random.randbytes(16) # ๐๏ธ b'M\x9dh\xfa\xee\x93i\x02\x17\xe2\x13\xa5\x03\xebh\xc8' print(random_bytes) print(len(random_bytes)) # ๐๏ธ 16
The random.randbytes() method was introduced in Python 3.9 and generates N random bytes.
The method should not be used for generating security tokens.
You can use the secrets
module if you need to generate security tokens.
The token_bytes()
method from the secrets
module generates a
cryptographically strong random byte string of N bytes.
import secrets random_bytes = secrets.token_bytes(8) print(random_bytes) # ๐๏ธ b'>C\xe3\xe3?m\xa4u' print(len(random_bytes)) # ๐๏ธ 8 # ------------------------------------------ random_bytes = secrets.token_bytes(16) # ๐๏ธ b'\x84\x84>\xe0]o\xda\x1e\xc8qL\xde\xf0\x8e\xc7\xec' print(random_bytes) print(len(random_bytes)) # ๐๏ธ 16
The secrets module is used for generating cryptographically strong random numbers for passwords, security tokens, etc.
The secrets.token_bytes method returns a random byte string of the given length.
If the number of bytes is not specified or is None
, a default value is used.
import secrets random_bytes = secrets.token_bytes() # ๐๏ธ b'\xcc\xed\xf2\xd6Q\x9e\x02\x02\x1d\xbe\xddu\xf9\x11\xd5\x015\xccT\xf4\xe4)/S\xd9N\xed\x0b\xb0;Xt' print(random_bytes) print(len(random_bytes)) # ๐๏ธ 32
Which approach you pick is a matter of personal preference.
If you need to generate security tokens, make sure to not use the
random.randbytes()
method.
To generate a random hex string:
os.urandom()
method to get a byte string of N random bytes.binascii.b2a_hex()
method to return the hexadecimal representation
of the binary data.import binascii import os result = binascii.b2a_hex(os.urandom(10)) print(result) # ๐๏ธ b'a28ad94dde798a004e4d' string = result.decode('utf-8') print(string) # ๐๏ธ a28ad94dde798a004e4d print(len(result)) # ๐๏ธ 20
The os.urandom() method
takes a size
argument and returns a cryptographically secure byte string of
size
random bytes.
How the method is implemented depends on the underlying operating system.
The binascii.b2a_hex method returns the hexadecimal representation of the supplied binary data.
You can use the bytes.decode()
method if you need to convert the bytes object
to a string.
import binascii import os result = binascii.b2a_hex(os.urandom(10)) print(result) # ๐๏ธ b'a28ad94dde798a004e4d' string = result.decode('utf-8') print(string) # ๐๏ธ a28ad94dde798a004e4d print(len(result)) # ๐๏ธ 20
The bytes.decode() method returns a
string decoded from the given bytes. The default encoding is utf-8
.
An alternative approach is to use the random.choices()
method.
This is a two-step process:
random.choices()
to select N digits from a sequence of hexadecimal
digits.str.join()
method to join the N digits into a string.import random def gen_random_hex_string(size): return ''.join(random.choices('0123456789abcdef', k=size)) result = gen_random_hex_string(16) print(result) # ๐๏ธ db688cb662842860
If you also need to include the capital letters A-F
, you can also use the
string.hexdigits
attribute.
import string # ๐๏ธ 0123456789abcdefABCDEF print(string.hexdigits)
The
random.choices()
method returns a k
sized list of elements chosen from the provided iterable
with replacement.
import random result = random.choices('0123456789abcdef', k=10) # ๐๏ธ ['f', '1', '0', '7', 'b', '4', 'a', '8', 'd', 'b'] print(result)
Once we have a list of hexadecimal digits, we can use the str.join()
method to
join the list into a string.
import random def gen_random_hex_string(size): return ''.join(random.choices('0123456789abcdef', k=size)) result = gen_random_hex_string(16) print(result) # ๐๏ธ e36fd2ec559d35d1
The str.join() method takes an iterable as an argument and returns a string which is the concatenation of the strings in the iterable.
The string the method is called on is used as the separator between the elements.
If you need to generate a cryptographically secure hex string, use the secrets
module.
The token_hex()
method from the secrets
module returns a random text string
in hexadecimal.
import secrets result = secrets.token_hex(16) print(result) # ๐๏ธ c39d47a82e4fda7cd43ca139db5cebb3 print(len(result)) # ๐๏ธ 32
The secrets module is used for generating cryptographically strong random numbers for passwords, security tokens, etc.
The secrets.token_hex method returns a random text string in hexadecimal.
The argument the method takes is the number of random bytes the string should contain. Each byte gets converted to 2 hex digits.
To generate a random hex color:
random.choices()
method to select 6 random hex symbols.str.join()
method to join the list into a string.import random def gen_random_hex_color(): hex_digits = '0123456789ABCDEF' return '#' + ''.join( random.choices(hex_digits, k=6) ) print(gen_random_hex_color()) # ๐๏ธ #6DB16C print(gen_random_hex_color()) # ๐๏ธ #8E5D29 print(gen_random_hex_color()) # ๐๏ธ #7593E1
We used the random.choices()
method to select 6 random hex symbols.
0-9
and the characters A-F
.The
random.choices
method returns a k
sized list of elements chosen from the provided iterable
with replacement.
import random # ๐๏ธ ['9', 'A', 'C', 'C', '2', 'C'] print(random.choices('0123456789ABCDEF', k=6))
random.choice()
version in older Python versionsThe random.choices()
method was introduced in Python 3.9. If you use an older
version, use the random.choice()
method.
import random def gen_random_hex_color(): hex_digits = '0123456789ABCDEF' return '#' + ''.join( random.choice(hex_digits) for _ in range(6) ) print(gen_random_hex_color()) # ๐๏ธ #6F1C2B print(gen_random_hex_color()) # ๐๏ธ #2B1364 print(gen_random_hex_color()) # ๐๏ธ #6F8E77
The random.choice() method takes a sequence and returns a random element from the non-empty sequence.
import random print(random.choice('bobby')) # ๐๏ธ "o"
Once we have a collection of random hex symbols, we can use the str.join()
method to join the characters into a string.
The str.join method takes an iterable as an argument and returns a string which is the concatenation of the strings in the iterable.
The string the method is called on is used as the separator between the elements.
The last step is to use the addition (+) operator to prepend a hash symbol to the string.
import random def gen_random_hex_color(): hex_digits = '0123456789ABCDEF' return '#' + ''.join( random.choices(hex_digits, k=6) ) print(gen_random_hex_color()) # ๐๏ธ #6DB16C
Alternatively, you can use a formatted string literal.
This is a two-step process:
random.randint()
method to get 3 random numbers from 0 to 255.import random def gen_random_hex_color(): def get_int(): return random.randint(0, 255) return f'#{get_int():02X}{get_int():02X}{get_int():02X}' print(gen_random_hex_color()) # ๐๏ธ #A5F627 print(gen_random_hex_color()) # ๐๏ธ #671D75 print(gen_random_hex_color()) # ๐๏ธ #B37340
The
random.randint()
function takes 2 numbers - a
and b
as parameters and returns a random
integer in the range.
Note that the range is inclusive - meaning both a
and b
can be returned.
f
.var1 = 'bobby' var2 = 'hadz' result = f'{var1}{var2}' print(result) # ๐๏ธ bobbyhadz
Make sure to wrap expressions in curly braces - {expression}
.
Formatted string literals also enable us to use the format specification mini-language in expression blocks.
The :02
syntax is used to pad each value with leading zeros to a fixed width
of 2.
def gen_random_hex_color(): def get_int(): return random.randint(0, 255) return f'#{get_int():02X}{get_int():02X}{get_int():02X}' print(gen_random_hex_color()) # ๐๏ธ #A5F627 print(gen_random_hex_color()) # ๐๏ธ #671D75
If the generated number is less than 10
, it gets padded to 2 digits.
The X
character stands for hex format.
It outputs the number in base 16, using uppercase letters for the digits above
9
.
The last step is to add a hash symbol at the beginning of the string.
Which approach you pick is a matter of personal preference. I'd use the
random.choices()
method because I find it easier to read.
You can learn more about the related topics by checking out the following tutorials: