ChatGPT解决这个技术问题 Extra ChatGPT

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

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

6U1S75

4Z4UKK

U911K4

这是一个非常受欢迎的问题。我希望专家将他对前 3 个答案的这些随机数的唯一性的看法,即字符串大小范围的碰撞概率,比如从 6 到 16。
@buffer 计算可能组合的数量很容易。 10 个数字 + 26 个字母 = 36 个可能的字符,6 的幂(字符串的长度)大约等于 20 亿。我对随机值的经验法则是“如果我为地球上的每个人生成值,他们每个人可以有多少值?”。在这种情况下,每个人的值将小于一个,所以如果这是为了识别用户或对象,那么字符太少了。一种替代方法是添加小写字母,这使您获得 62^6 = 近 570 亿个唯一值。
虽然考虑世界人口可能看起来很愚蠢,但这只是因为你想要一个巨大的缓冲来应对潜在的碰撞。查看生日问题:en.wikipedia.org/wiki/Birthday_problem
@buffer,那么您会对 this answer 感兴趣。
这不应该重命名为“加密安全随机字符串生成......”吗?

J
Joël Brigate

一句话回答:

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

加密更安全的版本: see this post

''.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 只是连接代表大写 ASCII 字符和数字的字符列表:

>>> 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 不会在内存中创建列表,而是动态生成元素,一个一个(更多关于这个here)。

我们不会要求创建 'n' 次字符串 elem,而是要求 Python 创建 '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'

@jorelli:这不是列表理解;这是一个生成器表达式。
@joreilli:我在答案中添加了一个关于此的快速注释,以及指向更详细答案的链接,该答案有关可迭代、列表理解、生成器以及最终的 yield 关键字。
@TKKocheran:你是说SystemRandom吗?如果没有,请提供网址。
很有用。有趣的是,Django 正在使用这段代码来生成密码 & CSRF 代币。虽然您应该将 random 替换为 random.SystemRandom()github.com/django/django/blob/…
@ Chiel92,random.sample 创建没有替换的样本,换句话说,没有重复字符的可能性,这不在 OP 的要求中。我认为这对于大多数应用程序来说是不可取的。
G
Georgy

这个 Stack Overflow 问题是“随机字符串 Python”的当前最高 Google 结果。当前的最佳答案是:

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

在 *nix 机器上使用 random.SystemRandom() 而不是随机使用 /dev/urandom,在 Windows 中使用 CryptGenRandom()。这些是加密安全的 PRNG。在需要安全 PRNG 的应用程序中使用 random.choice 而不是 random.SystemRandom().choice 可能具有潜在的破坏性,并且鉴于这个问题的流行,我敢打赌这个错误已经犯过很多次了。

如果您使用的是 python3.6 或更高版本,则可以使用 MSeifert's answer 中提到的新 secrets 模块:

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

模块文档还讨论了 generate secure tokensbest practices 的便捷方法。


是的,random 的官方标准库已发出警告:“警告:此模块的伪随机生成器不应用于安全目的。如果您使用 os.urandom() 或 SystemRandom需要一个加密安全的伪随机数生成器。”这是参考:random.SystemRandomos.urandom
很好的答案。小提示:您将其更改为 string.uppercase,这可能会导致意外结果,具体取决于区域设置。在涉及编码的情况下,使用 string.ascii_uppercase(或 string.ascii_letters + string.digits 用于 base62 而不是 base36)更安全。
小提示 - 最好使用 xrange 而不是 range,因为后者会生成一个内存列表,而前者会创建一个迭代器。
随机刺痛将永远是独一无二的吗?我想使用主键。
@shakthydoss:不。它可能返回“AAA000”,它是一个随机字符串,然后返回“AAA000”,它也是一个随机字符串。您必须明确添加唯一性检查。
o
oscfri

只需使用 Python 的内置 uuid:

如果 UUID 适合您的目的,请使用内置 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

+1用于思考问题。或许你可以简单解释一下 uuid1 和 uuid4 的区别。
uui1:根据主机 ID、序列号和当前时间生成 UUID。 uuid4:生成随机 UUID。
如果您想跳过字符串转换和连字符替换,您只需调用 my_uuid.get_hex() 或 uuid.uuid4().get_hex() ,它将返回从 uuid 生成的不带连字符的字符串。
截断 UUID 是个好主意吗?根据 string_length 的大小,碰撞的可能性可能是一个问题。
为什么要限制自己只使用十六进制字符。 Base64 或 Base32(仅适用于大写字符和 6 个不同的数字)用于编码随机 os.urandom() 字节序列。绕过 uuid 中间人以获得更快的速度!
A
Anurag Uniyal

一种更简单、更快但随机性稍差的方法是使用 random.sample 而不是单独选择每个字母,如果允许 n 次重复,请将随机基础扩大 n 倍,例如

import random
import string

char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))

注意: random.sample 防止字符重用,乘以字符集的大小使多次重复成为可能,但它们仍然不太可能,然后它们是纯随机选择。如果我们选择长度为 6 的字符串,并且我们选择“X”作为第一个字符,在选择示例中,第二个字符得到“X”的几率与将“X”作为第一个字符的几率相同第一个字符。在 random.sample 实现中,将“X”作为任何后续字符的几率仅为将其作为第一个字符的几率的 6/7


这种方式还不错,但不像单独选择每个字符那样随机,因为使用 sample 您永远不会两次列出相同的字符。当然,如果 N 高于 36,它也会失败。
对于给定的用例(如果没有重复就可以),我会说它仍然是最好的解决方案。
其中一个例子有重复,所以我怀疑他是否希望禁止重复。
如果 random.sample 阻止字符重用,则乘以字符集的大小可以使多次重复成为可能,但它们仍然不太可能,那么它们处于纯随机选择中。如果我们选择长度为 6 的字符串,并且我们选择“X”作为第一个字符,在选择示例中,第二个字符得到“X”的几率与将“X”作为第一个字符的几率相同第一个字符。在 random.sample 实现中,将“X”作为任何后续字符的几率仅为将其作为第一个字符的几率的 5/6。
当您在生成的字符串中移动时,重复特定字符的机会会下降。从 26 个大写字母加上 10 个数字生成一个 6 个字符的字符串,独立随机选择每个字符,任何特定字符串以 1/(36^6) 的频率出现。产生‘FU3WYE’和‘XXXXXX’的几率是一样的。在示例实现中,生成 'XXXXXX' 的机会是 (1/(36^6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 /6) * (1/6)) 由于 random.sample 的不可替换特性。在示例实现中,“XXXXXX”的可能性要低 324 倍。
Y
Yajo
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str 是一个随机值,例如 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str'CEA8B32E00934AAEA8C005A35D85A5C0'


uppercase_str[:N+1]
@Yajo 是的,我们可以限制使用切片
@Yajo:不,您不想分割十六进制值。与完整的大写字母和数字序列相比,您删除了熵。也许base32-encode这个值(稍微减少熵,从36 ** n到32 ** n,仍然比16 ** n好)。
@Yajo uuid 中的某些位不是随机的!它们用于指示 uuid 是哪个变体和版本,因此它们不是随机的,并且您获得的随机位比您预期的要少!要么完全理解截断时 UUID 的工作原理(阅读 RFC),要么更好的是,使用 python secrets 模块(或 python2 等效的 random.SystemRandom()),因为这为您提供了安全保证(与当前的 uuid 模块相比)。
B
Brutus

从 Python 3.6 开始,您应该使用 secrets module 如果您需要它是加密安全的 而不是 random 模块(否则此答案与@Ignacio Vazquez-Abrams 的答案相同):

from secrets import choice
import string

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

另一个注意事项:在 str.join 的情况下,列表理解比使用生成器表达式更快!


S
Skippy le Grand Gourou

一种更快、更简单、更灵活的方法是使用 strgen 模块 (pip install StringGenerator)。

生成包含大写字母和数字的 6 字符随机字符串:

>>> from strgen import StringGenerator as SG
>>> SG("[\u\d]{6}").render()
u'YZI2CI'

获取唯一列表:

>>> SG("[\l\d]{10}").render_list(5,unique=True)
[u'xqqtmi1pOk', u'zmkWdUr63O', u'PGaGcPHrX2', u'6RZiUbkk2i', u'j9eIeeWgEF']

保证字符串中有一个“特殊”字符:

>>> SG("[\l\d]{10}&[\p]").render()
u'jaYI0bcPG*0'

随机的 HTML 颜色:

>>> SG("#[\h]{6}").render()
u'#CEdFCa'

等等

我们需要意识到这一点:

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

其中可能没有数字(或大写字符)。

strgen 的开发时间比上述任何解决方案都快。 Ignacio 的解决方案是运行时执行速度最快的解决方案,并且是使用 Python 标准库的正确答案。但是你几乎不会以那种形式使用它。您将要使用 SystemRandom(如果不可用,则使用后备),确保表示所需的字符集,使用 unicode(或不使用),确保连续调用产生唯一的字符串,使用字符串模块字符类之一的子集,等等。这一切都需要比提供的答案更多的代码。各种泛化解决方案的尝试都有局限性,strgen 使用简单的模板语言以更简洁和表达能力更强的方式解决了这些问题。

它在 PyPI 上:

pip install StringGenerator

披露:我是 strgen 模块的作者。


请注意,如果安全方法不可用,这会默默地退回到密码不安全的 random.Random!当用户提供种子值时,它也会使用回退。当它使用加密安全方法时,不做一般保证。
C
Community

基于另一个 Stack Overflow 答案 Most lightweight way to create a random string and a random hexadecimal number,比接受的答案更好的版本是:

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

快多了。


这很好,虽然它只会使用“AF”而不是“AZ”。此外,当参数化 N 时,代码会变得不太好。
R
Russia Must Remove Putin

我以为还没有人回答这个问题,哈哈!但是,嘿,这是我自己的尝试:

import random

def random_alphanumeric(limit):
    #ascii alphabet of all alphanumerals
    r = (range(48, 58) + range(65, 91) + range(97, 123))
    random.shuffle(r)
    return reduce(lambda i, s: i + chr(s), r[:random.randint(0, len(r))], "")

我不会对此投反对票,但我认为对于如此简单的任务来说太复杂了。返回表达式是一个怪物。简单胜于复杂。
@CarlSmith,真的,我的解决方案对于这项任务来说似乎有点矫枉过正,但我知道其他更简单的解决方案,只是想找到一个好的答案的替代途径。没有自由,创造力就处于危险之中,因此我继续发布它。
J
John La Rooy

如果您需要一个随机字符串而不是 伪随机 字符串,则应使用 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))

os.urandom 怎么不是伪随机的?它可能使用更好的算法来生成更随机的数字,但它仍然是伪随机的。
@Tyilo,我知道 /dev/random/dev/urandom 之间的区别。问题是当没有足够的熵限制它的有用性时,/dev/random 会阻塞。对于 one time pad/dev/urandom 还不够好,但我认为它比伪随机要好。
我会说 /dev/random/dev/urandom 都是伪随机的,但这可能取决于您的定义。
s
sea-rob

与 Ignacio 发布的 random.choice() 方法相比,此方法稍快,但也更烦人。

它利用了伪随机算法的性质,并且按位和移位比为每个字符生成新的随机数更快。

# 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')

...创建一个生成器,每次 0..31 取出 5 个位数,直到一个都没有

...join() 生成器在具有正确位的随机数上的结果

使用 Timeit,对于 32 个字符的字符串,时间为:

[('generate_with_random_choice', 28.92901611328125),
 ('generate_with_randbits', 20.0293550491333)]

...但是对于 64 个字符串,随机数会输掉;)

除非我真的不喜欢我的同事,否则我可能永远不会在生产代码中使用这种方法。

编辑:更新以适应问题(仅限大写和数字),并使用按位运算符 & 和 >> 而不是 % 和 //


I
Ian Smith

使用 Numpy 的 random.choice() 函数

import numpy as np
import string        

if __name__ == '__main__':
    length = 16
    a = np.random.choice(list(string.ascii_uppercase + string.digits), length)                
    print(''.join(a))

文档在这里http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html


为什么我应该使用 numpy random 而不是 python stdlib random?
因为它允许在参数中提供更多选项,例如长度、可变概率和替换选择。
C
Carl Smith

我会这样做:

import random
from string import digits, ascii_uppercase

legals = digits + ascii_uppercase

def rand_string(length, char_set=legals):

    output = ''
    for _ in range(length): output += random.choice(char_set)
    return output

要不就:

def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )

A
Aseem

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

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

uuid 中的某些位不是随机的!它们用于指示 uuid 是哪个变体和版本,因此它们不是随机的,如果你截断它,你得到的随机位比你预期的要少!要么完全理解截断时 UUID 的工作原理(阅读 RFC),要么更好的是,使用 python secrets 模块(或 python2 等效的 random.SystemRandom()),因为这为您提供了安全保证(与当前的 uuid 模块相比)。
J
Javad
>>> import string 
>>> import random

以下逻辑仍然生成 6 个字符的随机样本

>>> print ''.join(random.sample((string.ascii_uppercase+string.digits),6))
JT7K3Q

无需乘以 6

>>> print ''.join(random.sample((string.ascii_uppercase+string.digits)*6,6))

TK82HK

但是这个变体将强制所有字符都不同。如果 N 大于 len(string.ascii_uppercase + string.digits) 它将不起作用
A
A.J. Uppal
>>> import random
>>> str = []
>>> chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
>>> num = int(raw_input('How long do you want the string to be?  '))
How long do you want the string to be?  10
>>> for k in range(1, num+1):
...    str.append(random.choice(chars))
...
>>> str = "".join(str)
>>> str
'tm2JUQ04CK'

random.choice 函数在列表中选择一个随机条目。您还可以创建一个列表,以便可以在 for 语句中附加字符。最后 str 是 ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'],但是 { 3} 会解决这个问题,留下 'tm2JUQ04CK'

希望这可以帮助!


很好,但您可以改用 range(num),而 str 可以是字符串 str += random.choice(chars)
S
Samy Vilar

对于那些喜欢函数式 python 的人:

from itertools import imap, starmap, islice, repeat
from functools import partial
from string import letters, digits, join
from random import choice

join_chars = partial(join, sep='')
identity = lambda o: o

def irand_seqs(symbols=join_chars((letters, digits)), length=6, join=join_chars, select=choice, breakup=islice):
    """ Generates an indefinite sequence of joined random symbols each of a specific length
    :param symbols: symbols to select,
        [defaults to string.letters + string.digits, digits 0 - 9, lower and upper case English letters.]
    :param length: the length of each sequence,
        [defaults to 6]
    :param join: method used to join selected symbol, 
        [defaults to ''.join generating a string.]
    :param select: method used to select a random element from the giving population. 
        [defaults to random.choice, which selects a single element randomly]
    :return: indefinite iterator generating random sequences of giving [:param length]
    >>> from tools import irand_seqs
    >>> strings = irand_seqs()
    >>> a = next(strings)
    >>> assert isinstance(a, (str, unicode))
    >>> assert len(a) == 6
    >>> assert next(strings) != next(strings)
    """
    return imap(join, starmap(breakup, repeat((imap(select, repeat(symbols)), None, length))))

它生成一个连接随机序列的无限[无限]迭代器,首先从给定池中生成一个随机选择的符号的无限序列,然后将此序列分解为长度部分,然后再连接,它应该与任何支持 getitem 的序列一起使用,默认情况下它只是生成随机的字母数字字母序列,尽管您可以轻松修改以生成其他内容:

例如生成随机数字元组:

>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> next(irand_tuples)
(0, 5, 5, 7, 2, 8)
>>> next(irand_tuples)
(3, 2, 2, 0, 3, 1)

如果您不想使用下一代,您可以简单地使其可调用:

>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> make_rand_tuples = partial(next, irand_tuples) 
>>> make_rand_tuples()
(1, 6, 2, 8, 1, 9)

如果您想动态生成序列,只需将连接设置为身份。

>>> irand_tuples = irand_seqs(xrange(10), join=identity)
>>> selections = next(irand_tuples)
>>> next(selections)
8
>>> list(selections)
[6, 3, 8, 2, 2]

正如其他人所提到的,如果您需要更多安全性,请设置适当的选择功能:

>>> from random import SystemRandom
>>> rand_strs = irand_seqs(select=SystemRandom().choice)
'QsaDxQ'

默认选择器是 choice ,它可以为每个块多次选择相同的符号,如果您希望为每个块最多选择一次相同的成员,那么一种可能的用法:

>>> from random import sample
>>> irand_samples = irand_seqs(xrange(10), length=1, join=next, select=lambda pool: sample(pool, 6))
>>> next(irand_samples)
[0, 9, 2, 3, 1, 6]

我们使用 sample 作为我们的选择器,进行完整的选择,所以块的长度实际上是 1,我们只需调用 next 来获取下一个完全生成的块,这个例子看起来有点麻烦,它是...


J
Jacob

(1) 这将为您提供所有大写字母和数字:

import string, random
passkey=''
for x in range(8):
    if random.choice([1,2]) == 1:
        passkey += passkey.join(random.choice(string.ascii_uppercase))
    else:
        passkey += passkey.join(random.choice(string.digits))
print passkey 

(2) 如果您以后想在密钥中包含小写字母,那么这也可以:

import string, random
passkey=''
for x in range(8):
    if random.choice([1,2]) == 1:
        passkey += passkey.join(random.choice(string.ascii_letters))
    else:
        passkey += passkey.join(random.choice(string.digits))
print passkey  

S
Stopit Donk

这是对 Anurag Uniyal 的回应和我自己正在研究的东西的看法。

import random
import string

oneFile = open('‪Numbers.txt', 'w')
userInput = 0
key_count = 0
value_count = 0
chars = string.ascii_uppercase + string.digits + string.punctuation

for userInput in range(int(input('How many 12 digit keys do you want?'))):
    while key_count <= userInput:
        key_count += 1
        number = random.randint(1, 999)
        key = number

        text = str(key) + ": " + str(''.join(random.sample(chars*6, 12)))
        oneFile.write(text + "\n")
oneFile.close()

C
Community

我正在查看不同的答案并花时间阅读 secrets 的文档

secrets 模块用于生成适用于管理数据(例如密码、帐户身份验证、安全令牌和相关机密)的加密强随机数。特别是,应该优先使用秘密,而不是随机模块中的默认伪随机数生成器,该生成器是为建模和模拟而设计的,而不是安全或密码学。

如果你想模仿像 Google Drive ID 这样的 ID,我发现了一个非常方便的功能:

secrets.token_urlsafe([nbytes=None]) 返回一个随机的 URL 安全文本字符串,包含 nbytes 随机字节。文本是 Base64 编码的,因此平均每个字节产生大约 1.3 个字符。如果 nbytes 为 None 或未提供,则使用合理的默认值。

按以下方式使用它:

import secrets
import math

def id_generator():
    id = secrets.token_urlsafe(math.floor(32 / 1.3))
    return id

print(id_generator())

输出一个 32 个字符长度的 id:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

我知道这与 OP 的问题略有不同,但我希望它对许多正在寻找我正在寻找的相同用例的人仍然有帮助。


N
Nishan

我使用这种方法从 a -> z 生成长度为 n 的随机字符串

导入随机 s = ''.join(random.choice([chr(i) for i in range(ord('a'),ord('z'))]) for _ in range(10))


N
Natasha
import string
from random import *
characters = string.ascii_letters + string.punctuation  + string.digits
password =  "".join(choice(characters) for x in range(randint(8, 16)))
print password

尽管此代码可能会回答问题,但提供有关 为什么 和/或 如何 回答问题的附加上下文将显着提高其长期价值。请edit您的回答以添加一些解释。
l
lawlie8
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="")

这里可以在 for 循环中更改字符串的长度,即 for i in range(1,length) 这是一种简单易懂的算法。它使用列表,因此您可以丢弃不需要的字符。


H
Hackaholic

一个简单的:

import string
import random
character = string.lowercase + string.uppercase + string.digits + string.punctuation
char_len = len(character)
# you can specify your password length here
pass_len = random.randint(10,20)
password = ''
for x in range(pass_len):
    password = password + character[random.randint(0,char_len-1)]
print password

m
mrvol

我想建议你下一个选项:

import crypt
n = 10
crypt.crypt("any sring").replace('/', '').replace('.', '').upper()[-n:-1]

偏执模式:

import uuid
import crypt
n = 10
crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1]

P
Pedro Lobito
import string, random
lower = string.ascii_lowercase
upper = string.ascii_uppercase
digits = string.digits
special = '!"£$%^&*.,@#/?'

def rand_pass(l=4, u=4, d=4, s=4):
    p = []
    [p.append(random.choice(lower)) for x in range(l)]
    [p.append(random.choice(upper)) for x in range(u)]
    [p.append(random.choice(digits)) for x in range(d)]
    [p.append(random.choice(special)) for x in range(s)]
    random.shuffle(p)
    return "".join(p)

print(rand_pass())
# @5U,@A4yIZvnp%51

R
Raymond Hettinger

面向安全的方法

对于与安全相关的任何事情,我们的建议是避免“滚动您拥有”并使用专门针对安全性进行审查的 secrets module

这是来自 best practices section of the docs

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

由于您特别要求输入大写字母,因此您可以将 ascii_uppercase 替换为 ascii_letters,或者将密码大写:

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'

B
Bi Ao

两种方法:

import random, math

def randStr_1(chars:str, length:int) -> str:
    chars *= math.ceil(length / len(chars))
    chars = letters[0:length]
    chars = list(chars)
    random.shuffle(characters)

    return ''.join(chars)

def randStr_2(chars:str, length:int) -> str:
    return ''.join(random.choice(chars) for i in range(chars))

基准 :

from timeit import timeit

setup = """
import os, subprocess, time, string, random, math

def randStr_1(letters:str, length:int) -> str:
    letters *= math.ceil(length / len(letters))
    letters = letters[0:length]
    letters = list(letters)
    random.shuffle(letters)
    return ''.join(letters)

def randStr_2(letters:str, length:int) -> str:
    return ''.join(random.choice(letters) for i in range(length))
"""

print('Method 1 vs Method 2', ', run 10 times each.')

for length in [100,1000,10000,50000,100000,500000,1000000]:
    print(length, 'characters:')

    eff1 = timeit("randStr_1(string.ascii_letters, {})".format(length), setup=setup, number=10)
    eff2 = timeit("randStr_2(string.ascii_letters, {})".format(length), setup=setup, number=10)
    print('\t{}s : {}s'.format(round(eff1, 6), round(eff2, 6)))
    print('\tratio = {} : {}\n'.format(eff1/eff1, round(eff2/eff1, 2)))

输出 :

Method 1 vs Method 2 , run 10 times each.

100 characters:
    0.001411s : 0.00179s
    ratio = 1.0 : 1.27

1000 characters:
    0.013857s : 0.017603s
    ratio = 1.0 : 1.27

10000 characters:
    0.13426s : 0.151169s
    ratio = 1.0 : 1.13

50000 characters:
    0.709403s : 0.855136s
    ratio = 1.0 : 1.21

100000 characters:
    1.360735s : 1.674584s
    ratio = 1.0 : 1.23

500000 characters:
    6.754923s : 7.160508s
    ratio = 1.0 : 1.06

1000000 characters:
    11.232965s : 14.223914s
    ratio = 1.0 : 1.27

第一种方法的性能更好。


s
socketpair

生成包含字母、数字、“_”和“-”的随机 16 字节 ID

os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))


S
Sahith Kurapati

如果您想要一个易于使用但高度可定制的密钥生成器,请使用 key-generator pypi 包。

这是 GitHub 存储库,您可以在其中找到完整的文档。

您可以自定义它以提供您想要的字符串 jist,并提供更多选项。这是一个例子:

from key_generator.key_generator import generate

custom_key = generate(2, ['-', ':'], 3, 10, type_of_value = 'char', capital = 'mix', seed = 17).get_key()
print(custom_key)  # ZLFdHXIUe-ekwJCu

希望这可以帮助 :)

免责声明:这使用了我制作的 key-generator 库。