I want to generate a string of size N.
It should be made up of numbers and uppercase English letters such as:
This Stack Overflow quesion is the current top Google result for "random string Python". The current top answer is:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
This is an excellent method, but the PRNG in random is not cryptographically secure. I assume many people researching this question will want to generate random strings for encryption or passwords. You can do this securely by making a small change in the above code:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
Using random.SystemRandom()
instead of just random uses /dev/urandom on *nix machines and CryptGenRandom()
in Windows. These are cryptographically secure PRNGs. Using random.choice
instead of random.SystemRandom().choice
in an application that requires a secure PRNG could be potentially devastating, and given the popularity of this question, I bet that mistake has been made many times already.
If you're using python3.6 or above, you can use the new secrets module as mentioned in MSeifert's answer:
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
The module docs also discuss convenient ways to generate secure tokens and best practices.
import random
q=2
o=1
list =[r'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','s','0','1','2','3','4','5','6','7','8','9','0']
while(q>o):
print("")
for i in range(1,128):
x=random.choice(list)
print(x,end="")
Here length of string can be changed in for loop i.e for i in range(1,length) It is simple algorithm which is easy to understand. it uses list so you can discard characters that you do not need.
Generate random 16-byte ID containig letters, digits, '_' and '-'
os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))
This method is slightly faster, and slightly more annoying, than the random.choice() method Ignacio posted.
It takes advantage of the nature of pseudo-random algorithms, and banks on bitwise and and shift being faster than generating a new random number for each character.
# must be length 32 -- 5 bits -- the question didn't specify using the full set
# of uppercase letters ;)
_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
def generate_with_randbits(size=32):
def chop(x):
while x:
yield x & 31
x = x >> 5
return ''.join(_ALPHABET[x] for x in chop(random.getrandbits(size * 5))).ljust(size, 'A')
...create a generator that takes out 5 bit numbers at a time 0..31 until none left
...join() the results of the generator on a random number with the right bits
With Timeit, for 32-character strings, the timing was:
[('generate_with_random_choice', 28.92901611328125),
('generate_with_randbits', 20.0293550491333)]
...but for 64 character strings, randbits loses out ;)
I would probably never use this approach in production code unless I really disliked my co-workers.
edit: updated to suit the question (uppercase and digits only), and use bitwise operators & and >> instead of % and //
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
is a random value like 'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = lowercase_str.upper()
uppercase_str
is 'CEA8B32E00934AAEA8C005A35D85A5C0'
A simpler, faster but slightly less random way is to use random.sample
instead of choosing each letter separately, If n-repetitions are allowed, enlarge your random basis by n times e.g.
import random
import string
char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))
Note: random.sample prevents character reuse, multiplying the size of the character set makes multiple repetitions possible, but they are still less likely then they are in a pure random choice. If we go for a string of length 6, and we pick 'X' as the first character, in the choice example, the odds of getting 'X' for the second character are the same as the odds of getting 'X' as the first character. In the random.sample implementation, the odds of getting 'X' as any subsequent character are only 6/7 the chance of getting it as the first character