如何生成大小为N的字符串,由数字和大写英文字母组成,例如:

6个754z4英国U911K4型


当前回答

如果需要随机字符串而不是伪随机字符串,则应使用os.urandom作为源

from os import urandom
from itertools import islice, imap, repeat
import string

def rand_string(length=5):
    chars = set(string.ascii_uppercase + string.digits)
    char_gen = (c for c in imap(urandom, repeat(1)) if c in chars)
    return ''.join(islice(char_gen, None, length))

其他回答

这个堆栈溢出问题是当前Google搜索“随机字符串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在*nix机器上使用/dev/urandom,在Windows中使用CryptGenRandom(。这些是加密安全的PRNG。在需要安全PRNG的应用程序中使用random.choice而不是random.SystemRandom().choice可能会带来潜在的破坏性,鉴于这个问题的流行性,我敢打赌这个错误已经犯过很多次了。

如果您使用的是python3.6或更高版本,您可以使用MSeiffet回答中提到的新秘密模块:

''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))

模块文档还讨论了生成安全令牌的便捷方法和最佳实践。

到目前为止,没有一个答案能保证存在某些类别的字符,如大写、小写、数字等;因此,其他答案可能会导致密码没有数字等。奇怪的是,这样的功能不是标准库的一部分。以下是我使用的:

def random_password(*, nchars = 7, min_nupper = 3, ndigits = 3, nspecial = 3, special=string.punctuation):
    letters = random.choices(string.ascii_lowercase, k=nchars)
    letters_upper = random.choices(string.ascii_uppercase, k=min_nupper)
    digits = random.choices(string.digits, k=ndigits)
    specials = random.choices(special, k=nspecial)

    password_chars = letters + letters_upper + digits + specials
    random.shuffle(password_chars)

    return ''.join(password_chars)

有时0(零)和O(字母O)可能会令人困惑。所以我用

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')

基于另一个Stack Overflow答案,创建随机字符串和随机十六进制数的最轻量级方法,比公认答案更好的版本是:

('%06x' % random.randrange(16**6)).upper()

更快。

面向安全的方法

我们对任何安全相关的建议都是避免“自己动手”,并使用经过专门安全审查的机密模块。

这来自文档的最佳实践部分:

import string
import secrets
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(8))

由于您特别要求使用大写字母,因此您可以用ascii_capsaper替换ascii_cletters,或者只使用以下内容将密码大写:

password = password.upper()

不以安全为目的的标准方法

这个问题的规范方法(如指定)使用随机模块中的choices()函数:

>>> from random import choices
>>> from string import ascii_uppercase, digits

>>> population = ascii_uppercase + digits
>>> str.join('', choices(population, k=6))
'6JWF1H'