大写字母和数字的随机字符串生成
我想生成一个长度为N的字符串,这个字符串由数字和大写英文字母组成,比如:
- 6U1S75
- 4Z4UKK
- U911K4
36 个回答
直接使用Python自带的uuid模块:
如果UUID(通用唯一识别码)满足你的需求,可以使用Python自带的uuid模块。
一行解决方案:
import uuid; uuid.uuid4().hex.upper()[0:6]
详细版本:
示例:
import uuid
uuid.uuid4() #uuid4 => full random uuid
# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')
如果你需要特定的格式(比如“6U1S75”),可以这样做:
import uuid
def my_random_string(string_length=10):
"""Returns a random string of length string_length."""
random = str(uuid.uuid4()) # Convert UUID format to a Python string.
random = random.upper() # Make all characters uppercase.
random = random.replace("-","") # Remove the UUID '-'.
return random[0:string_length] # Return the random string.
print(my_random_string(6)) # For example, D9E50C
这个Stack Overflow的问题是关于“在Python中生成随机字符串”的搜索结果中排名第一的。当前最受欢迎的回答是:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
这个方法非常好,但这里提到的随机数生成器(PRNG)并不安全,特别是对于加密来说。我想很多人研究这个问题是为了生成加密用的随机字符串或密码。你可以通过对上面的代码做一个小改动来安全地生成随机字符串:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
使用random.SystemRandom()
代替普通的random,这样在类Unix系统上会使用/dev/urandom,而在Windows上会使用CryptGenRandom()
。这些都是安全的随机数生成器。如果在需要安全随机数生成器的应用中使用random.choice
而不是random.SystemRandom().choice
,可能会造成严重后果。考虑到这个问题的受欢迎程度,我敢打赌这个错误已经被很多人犯过了。
如果你使用的是Python 3.6或更高版本,可以使用新的secrets模块,正如MSeifert的回答中提到的:
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
一行代码的答案:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
或者从Python 3.6开始,可以用更短的方式,使用 random.choices()
:
''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
更安全的版本: 请查看这个帖子
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
详细说明,带有可重用的干净函数:
>>> import string
>>> import random
>>> def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
... return ''.join(random.choice(chars) for _ in range(size))
...
>>> id_generator()
'G5G74W'
>>> id_generator(3, "6793YUIO")
'Y3U'
它是如何工作的?
我们导入了 string
模块,它包含了一些常见的ASCII字符序列,还有 random
模块,用于生成随机数。
string.ascii_uppercase + string.digits
只是把表示大写字母和数字的字符列表连接在一起:
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
接着,我们用列表推导式来创建一个包含'n'个元素的列表:
>>> range(4) # range create a list of 'n' numbers
[0, 1, 2, 3]
>>> ['elem' for _ in range(4)] # we use range to create 4 times 'elem'
['elem', 'elem', 'elem', 'elem']
在上面的例子中,我们用 [
来创建列表,但在 id_generator
函数中我们没有这样做,这样Python就不会在内存中创建整个列表,而是一个一个地生成元素(更多内容可以在 这里找到)。
我们不是让Python创建'n'次字符串 elem
,而是让它创建'n'次从字符序列中随机选出的字符:
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
因此 random.choice(chars) for _ in range(size)
实际上是在创建一个包含 size
个字符的序列。这些字符是从 chars
中随机选出的:
>>> [random.choice('abcde') for _ in range(3)]
['a', 'b', 'b']
>>> [random.choice('abcde') for _ in range(3)]
['e', 'b', 'e']
>>> [random.choice('abcde') for _ in range(3)]
['d', 'a', 'c']
然后我们只需用一个空字符串将它们连接起来,这样序列就变成了一个字符串:
>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'