This is a Python script that generates a grid of random HTML colors. It works by reading random data from /dev/urandom and then encoding it as a hexadecimal string. This string is spit into individual values that will be represented as a color.
I am wanting to know if this is the best way to generate random values for this task. Would it be better to use the random module? Or is my method more beneficial for this task?
WIDTH = 64
HIGHT = 5
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
data = file("/dev/urandom").read(HIGHT*WIDTH*3).encode("hex")
colors = ""
count = 0
for byte in chunks(data, 6):
if count == WIDTH:
colors+="<br>"
count=0
count+=1
colors+="""<p style="color:%s; display:inline;">■</p>""" % (byte)
file("colors.html", "w").write(colors)
This is the output:
Screenshot
2 Answers 2
An implementation that uses the random module has the benefit of being platform independent. This code isn't going to run so well if you try it on Windows.
There is also another alternative. os.urandom() will use the underlying os to provide the random values.
On a UNIX-like system this will query
/dev/urandom, and on Windows it will useCryptGenRandom().
You can also use random.SystemRandom() if you still want the OS source, but want to use the interface provided by random.
This answer provides an implementation of chunks() that iterates instead of constructing a list of all the chunks.
I would also lean towards an implementation that opens the output file first, then writes to it as it iterates over the chunks. This way, you won't need to build a huge string in memory before writing it to disk. Similarly, I would generate the random values as needed.
By using
/dev/urandomyou make it hard for someone to run your code on Windows. Instead, use the built-in functionos.urandom.But what are these colours going to be used for? Do you really care whether they are generated using cryptographically secure random numbers? It looks like an application for which ordinary pseudo-random numbers from the
randommodule will be perfectly adequate.The word "height" has an "e" in it.
str.encode('hex')isn't portable to Python 3. Instead, you should usebinascii.hexlify.The name
byteseems like a bad name for a variable that contains a 6-character-long string.You read a big block of random data and then use the
chunksfunction to split it up. But it would be simpler to read one chunk of random data at a time—then you wouldn't need thechunksfunction.Similarly, you build a big string and then write it to the output all in one go. But it would be simpler to open the output file and then write one small string at a time to it.
The entity reference
■is unclear. I would use theunicodedatamodule and writeunicodedata.lookup('BLACK SQUARE')so that the meaning is clearWhy do you use
<p>if you are going to specifydisplay:inline? Why not use<span>instead?
Putting all this together, I'd write:
from random import randrange
from unicodedata import lookup
WIDTH = 64
HEIGHT = 5
SQUARE = ord(lookup('BLACK SQUARE'))
FORMAT = '<span style="color:{{:06x}}">&#x{:x};</span>'.format(SQUARE)
with open('colors.html', 'w') as f:
for _ in range(HEIGHT):
for _ in range(WIDTH):
f.write(FORMAT.format(randrange(0x1000000)))
f.write('<br>')