06 August 2017

Generating random data using Python

The Python standard library's random module has a randrange function which generates random integers in a range.

Example:

>>> from random import randrange
>>> randrange(10), randrange(10), randrange(10)
(6, 4, 9)

Let's generate random bytes using randrange. A byte can be represented as an integer from 0 to 256 exclusive. To convert the integer to a bytes object, use Python 3's int.to_bytes method:

>>> x=123
>>> x.to_bytes(1, 'little')
b'{'

Here is a function to generate a random string of n bytes in a given range:

def random_bytes(n, low=0, high=256):
    bb = b'\0' # Dummy initializer.
    for i in range(n):
        x = random.randrange(low,high)
        bb += x.to_bytes(1, 'little')
    return bb[1:]


The initializer to b'\0' is only used to get the byte string going; a 0-length bytes object will not work; it is treated as a str instead. If you are using Python 2, the x.to_bytes method is unavailable; an alternative is to use the to_bytes function described in this Stack Overflow QA about to_bytes:

def to_bytes(n, length, endianness='big'):
    h = '%x' % n
    s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex')
    return s if endianness == 'big' else s[::-1]
 
Python 2 example:

>>> x=126
>>> to_bytes(x, 1, 'little')
'~' 

By using the range [32..256), we can generate interesting Latin-1 text strings on the terminal:

random_bytes.py:

(... imports)

def arg(n, default=None):
    import sys
    try:
        return sys.argv[n]
    except IndexError:
        return default
   
if __name__ == '__main__':
    nbytes = int(arg(1, default=20))
    bytes = random_bytes(nbytes, 32, 256)
    print(bytes.decode('Latin-1'))


Using random_bytes:

> python random_bytes.py 100
"v6┬▓├®5O[┬øwX┬¿├ï┬ÑXR┬î┬▓zR├ì┬╣/MN{┬éH├│├¥├Ñ├ø9(_├¥A┬½├┐┬Å├½┬×6┬Ñ┬╣├¼p├¢I┬ª┬¢┬¡c├âu5┬óQ├│┬╣├Å[i}├║QbH├«PQ├Ç┬è├ó├ñ
├£O{┬û├Á├¼┬À├╣┬çV┬░├É├æ├À┬╝├®┬ê├Æ|┬ô┬ê^┬░├ø├£ ├ç├¿┬ê\]├ñ├Ä5┬®q├â├Ø├øs├Á┬©┬ï┬│├║┬å├╣OgHW┬©├®┬úc|┬¡l-y├Ö├®G*├Æn3├▓├Ñ
Ãï˜ÆÀD{óa‰¨‰œ)Ö¢




Suggested Exercises

  • Extend random_bytes to generate random characters in encodings other than Latin-1. For example, the command random_bytes 100 utf-8 might generate (at least) 100 bytes of UTF-8 encoded data.
  • Create a program random_walk that simulates a random walk in a 100x100 point coordinate space. Let (0,0) be the upper-left coordinate of the space, and let (99,99) be the lower right. You start at (50,50). At each step, move a random displacement. By convention, positive and negative x displacements are to the right and left, respectively, and positive and negative y displacements are downward and upward, respectively. Output (x,y) coordinate pairs for each of the visited n positions during the walk. Example:

> random_walk 50
(50,50)
(79,39)
(90,49)
(...)

  • Define a small class hierarchy of geometrical shapes (e.g. Circle, Square) with parameters of your choosing. For example, a Circle might have parameters for its radius and center point. Using the shape hierarchy, create a program that generates random shapes, where each parameter is randomly chosen within some convenient limits. For example, you might decide that a Circle should have a radius of at least 10 but no more than 70. Print a text representation (i.e. repr) of each randomly generated shape. Example:

> random_shapes 10
Circle(Point(12,34), 58)
Square(Point(80,40), Point(95,68))
(...)

References

random - The Python Standard Library (Python 2)
random - The Python Standard Library (Python 3)
Stack Overflow - Has Python 3 to_bytes been back-ported to python 2.7?

Files

random_bytes-0.0.1.zip

No comments:

Post a Comment