Question or problem about Python programming:
What is the most lightweight way to create a random string of 30 characters like the following?
And an hexadecimal number of 30 digits like the followin?
How to solve the problem:
Solution 1:
I got a faster one for the hex output. Using the same t1 and t2 as above:
>>> t1 = timeit.Timer("''.join(random.choice('0123456789abcdef') for n in xrange(30))", "import random") >>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t3 = timeit.Timer("'%030x' % random.randrange(16**30)", "import random") >>> for t in t1, t2, t3: ... t.timeit() ... 28.165037870407104 9.0292739868164062 5.2836320400238037
t3
only makes one call to the random module, doesn’t have to build or read a list, and then does the rest with string formatting.
Solution 2:
30 digit hex string:
>>> import os,binascii >>> print binascii.b2a_hex(os.urandom(15)) "c84766ca4a3ce52c3602bbf02ad1f7"
The advantage is that this gets randomness directly from the OS, which might be more secure and/or faster than the random(), and you don’t have to seed it.
Solution 3:
In Py3.6+, another option is to use the new standard secrets
module:
>>> import secrets >>> secrets.token_hex(15) '8d9bad5b43259c6ee27d9aadc7b832' >>> secrets.token_urlsafe(22) # may include '_-' unclear if that is acceptable 'teRq7IqhaRU0S3euX1ji9f58WzUkrg'
Solution 4:
import string import random lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)] str = "".join(lst) print str ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb
Solution 5:
Dramatically faster solution than those here:
timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits") 0.8056681156158447
Solution 6:
Note: random.choice(string.hexdigits)
is incorrect, because string.hexdigits
returns 0123456789abcdefABCDEF
(both lowercase and uppercase), so you will get a biased result, with the hex digit ‘c’ twice as likely to appear as the digit ‘7’. Instead, just use random.choice('0123456789abcdef')
.
Solution 7:
Another Method :
from Crypto import Random import binascii my_hex_value = binascii.hexlify(Random.get_random_bytes(30))
The point is : byte value is always equal to the value in hex.
Solution 8:
one-line function:
import random import string def generate_random_key(length): return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length)) print generate_random_key(30)
Solution 9:
In [1]: import random In [2]: hex(random.getrandbits(16)) Out[2]: '0x3b19'
Solution 10:
Incidentally, this is the result of using timeit
on the two approaches that have been suggested:
Using random.choice()
:
>>> t1 = timeit.Timer("''.join(random.choice(string.hexdigits) for n in xrange(30))", "import random, string") >>> t1.timeit() 69.558588027954102
Using binascii.b2a_hex()
:
>>> t2 = timeit.Timer("binascii.b2a_hex(os.urandom(15))", "import os, binascii") >>> t2.timeit() 16.288421154022217