Most lightweight way to create a random string and a random hexadecimal number

Python

Python Problem Overview


What is the most lightweight way to create a random string of 30 characters like the following?

> ufhy3skj5nca0d2dfh9hwd2tbk9sw1

And an hexadecimal number of 30 digits like the followin?

> 8c6f78ac23b4a7b8c0182d7a89e9b1

Python Solutions


Solution 1 - Python

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 - Python

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 - Python

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 - Python

import string
import random
lst = [random.choice(string.ascii_letters + string.digits) for n in xrange(30)]
s = "".join(lst)
print s
ocwbKCiuAJLRJgM1bWNV1TPSH0F2Lb

Solution 5 - Python

Dramatically faster solution than those here:

timeit("'%0x' % getrandbits(30 * 4)", "from random import getrandbits")
0.8056681156158447

Solution 6 - Python

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 - Python

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 8 - Python

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 9 - Python

In [1]: import random                                    

In [2]: hex(random.getrandbits(16))                      
Out[2]: '0x3b19'

Solution 10 - Python

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

Solution 11 - Python

There's a faster one compared to what jcdyer has mentioned. This takes ~50% of his fastest method.

from numpy.random.mtrand import RandomState
import binascii
rand = RandomState()

lo = 1000000000000000
hi = 999999999999999999
binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:30]

>>> timeit.Timer("binascii.b2a_hex(rand.randint(lo,hi,2).tostring())[:30]", \
...                 'from __main__ import lo,hi,rand,binascii').timeit()
1.648831844329834         <-- this is on python 2.6.6
2.253110885620117         <-- this on python 2.7.5

If you want in base64:

binascii.b2a_base64(rand.randint(lo, hi, 3).tostring())[:30]

You can change the size parameter passed to randint (last arg) to vary the output length based on your requirement. So, for a 60 char one:

binascii.b2a_hex(rand.randint(lo, hi, 4).tostring())[:60]

Solution 12 - Python

This is for sure not the most lightweight version, but it is random and it's easy to adjust the alphabet / length you want:

import random

def generate(random_chars=12, alphabet="0123456789abcdef"):
    r = random.SystemRandom()
    return ''.join([r.choice(alphabet) for i in range(random_chars)])

Solution 13 - Python

adding one more answer to the mix that performs faster than @eemz solution and is also fully alphanumeric. Note that this does not give you a hexidecimal answer.

import random
import string

LETTERS_AND_DIGITS = string.ascii_letters + string.digits

def random_choice_algo(width):
  return ''.join(random.choice(LETTERS_AND_DIGITS) for i in range(width))

def random_choices_algo(width):
  return ''.join(random.choices(LETTERS_AND_DIGITS, k=width))


print(generate_random_string(10))
# prints "48uTwINW1D"

a quick benchmark yields

from timeit import timeit
from functools import partial

arg_width = 10
print("random_choice_algo", timeit(partial(random_choice_algo, arg_width)))
# random_choice_algo 8.180561417000717
print("random_choices_algo", timeit(partial(random_choices_algo, arg_width)))
# random_choices_algo 3.172438014007639

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionxRobotView Question on Stackoverflow
Solution 1 - PythonjcdyerView Answer on Stackoverflow
Solution 2 - PythonwumpView Answer on Stackoverflow
Solution 3 - PythonAChampionView Answer on Stackoverflow
Solution 4 - PythoneemzView Answer on Stackoverflow
Solution 5 - PythonKurt SpindlerView Answer on Stackoverflow
Solution 6 - PythonyaronfView Answer on Stackoverflow
Solution 7 - PythonBoubaView Answer on Stackoverflow
Solution 8 - PythondsgdfgView Answer on Stackoverflow
Solution 9 - PythonBobView Answer on Stackoverflow
Solution 10 - PythonDavid NarayanView Answer on Stackoverflow
Solution 11 - PythonEthanView Answer on Stackoverflow
Solution 12 - PythonMartin ThomaView Answer on Stackoverflow
Solution 13 - PythonandykaisView Answer on Stackoverflow