大写字母和数字的随机字符串生成

1753 投票
36 回答
1403583 浏览
提问于 2025-04-15 19:14

我想生成一个长度为N的字符串,这个字符串由数字和大写英文字母组成,比如:

  • 6U1S75
  • 4Z4UKK
  • U911K4

36 个回答

274

直接使用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
650

这个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))

这个模块的文档还讨论了方便的方式来生成安全的令牌最佳实践

3222

一行代码的答案:

''.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'

撰写回答