它应该由数字和大写英文字母组成,例如:
6U1S75
4Z4UKK
U911K4
如何以pythonic方式实现此目标?
#1 楼
在一行中回答:''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
或更短,使用
random.choices()
从Python 3.6开始:''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
A加密方式更安全的版本;请参阅https://stackoverflow.com/a/23728630/2213647:
''.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的列表'elements:
>>> 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'倍。 '随机字符,取自字符序列:q4312 078q
因此,
random.choice(chars) for _ in range(size)
实际上正在创建一个size
字符序列。从chars
中随机选取的字符:>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'
然后我们将它们与空字符串连接在一起,这样序列就变成了字符串:
>>> [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']
评论
@jorelli:这不是列表理解;这是一个生成器表达式。
–伊格纳西奥·巴斯克斯(Ignacio Vazquez-Abrams)
2011年6月9日在20:34
@joreilli:我在答案中添加了一个简短的注释,并提供了有关可迭代,列表理解,生成器以及最终yield关键字的更详细答案的链接。
– e-satis
2011年11月2日,14:54
我用xrange代替range。
– Jan-Philip Gehrcke博士
13年7月23日在12:51
很有用。有趣的是,Django正在使用这段代码来生成密码和CSRF令牌。虽然您应该将random替换为random.SystemRandom():github.com/django/django/blob/…
–用户
14年6月21日在7:03
@ Chiel92,random.sample创建样本时不会替换,换句话说,不可能重复字符,这不是OP的要求。我认为这对于大多数应用程序来说不是理想的。
–肿瘤科医生
2014年8月12日下午3:18
#2 楼
该堆栈溢出问题是“随机字符串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))
使用
random.SystemRandom()
而不是仅在* nix机器上随机使用/ dev / urandom以及在* nix机器上使用CryptGenRandom()
视窗。这些是加密安全的PRNG。在需要安全PRNG的应用程序中使用random.choice
代替random.SystemRandom().choice
可能会造成灾难性的后果,并且鉴于这个问题的普遍性,我敢打赌,这个错误已经犯过很多次了。如果您使用的是python3.6或更高版本,您可以使用MSeifert的答案中提到的新Secrets模块: 。
评论
是的,随机的官方标准库已发出警告:“警告:出于安全目的,不应使用此模块的伪随机数生成器。如果需要加密安全的伪随机数生成器,请使用os.urandom()或SystemRandom。 。”这是参考:random.SystemRandom和os.urandom
–主63。 Ĵ
2015年5月16日14:30
好答案。小提示:您将其更改为string.uppercase,这可能导致意外结果,具体取决于语言环境集。在涉及编码的情况下,使用string.ascii_uppercase(或base62而不是base36的string.ascii_letters + string.digits)更安全。
– Blixt
15年5月17日在18:03
小注释-最好使用xrange而不是range,因为后者会生成内存列表,而前者会创建迭代器。
– guyarad
16年7月31日在11:44
随机的ing会永远是唯一的吗?我想使用主键。
– shakthydoss
16-09-27在8:45
@ shakthydoss:不。它可以返回“ AAA000”(它是一个随机字符串)和下一个“ AAA000”(它也是一个随机字符串)。您必须显式添加唯一性检查。
–杂件
18年3月2日在11:15
#3 楼
只需使用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之间的区别。
–托马斯·阿勒
2014年1月29日12:36
uui1:根据主机ID,序列号和当前时间生成UUID。 uuid4:生成随机UUID。
– Bijan
2014年3月14日下午5:19
如果要跳过字符串转换和连字符替换,只需调用my_uuid.get_hex()或uuid.uuid4()。get_hex(),它就会返回从没有连字符的uuid生成的字符串。
–dshap
2014年4月11日0:50
截断UUID是个好主意吗?根据string_length的大小,可能会引起冲突。
–用户
14年6月21日在7:01
为什么限制自己只使用十六进制字符。 Base64或Base32(仅适用于大写字符和6个不同的数字),用于编码随机的os.urandom()字节序列。绕过uuid中间人以提高速度!
–马丁·彼得斯(Martijn Pieters)♦
18年1月24日在13:39
#4 楼
一种更简单,更快但稍少的随机方法是使用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
评论
这种方法还不错,但它不如分别选择每个字符那么随意,就像使用样本一样,您永远都不会两次列出相同的字符。当然,如果N大于36,它也会失败。
– bobince
2010-2-13在12:54
对于给定的用例(如果没有可以重复的话),我会说这仍然是最好的解决方案。
–阿努拉格(Anurag Uniyal)
2010-2-13 14:30
其中一个例子有重复,因此我怀疑他是否希望禁止重复。
–马克·拜尔斯
2010-2-13在14:34
如果random.sample阻止字符重用,则乘以字符集的大小可以进行多次重复,但是与纯随机选择相比,它们的可能性仍然较小。如果我们选择长度为6的字符串,并选择“ X”作为第一个字符,则在选择示例中,第二个字符获得“ X”的几率与获得“ X”作为第二个字符的几率相同第一个字符。在random.sample实现中,将“ X”作为任何后续字符的几率仅为将其作为第一个字符的机会的5/6。
– pcurry
13年8月31日在19:11
在生成的字符串中移动时,重复获得特定字符的机会会下降。从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倍。
– pcurry
13年8月31日在19:24
#5 楼
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
是类似'cea8b32e00934aaea8c005a35d85a5c0'
的随机值uppercase_str = lowercase_str.upper()
uppercase_str
是'CEA8B32E00934AAEA8C005A35D85A5C0'
评论
uppercase_str [:N + 1]
– Yajo
16年5月12日在15:51
@Yajo是的,我们可以限制使用切片
– Savad KP
16年5月13日在4:40
@Yajo:不,您不想切片十六进制值。与完整的大写字母和数字序列相比,您可以删除熵。也许可以用base32编码该值(熵从36 ** n稍微降低到32 ** n,但仍然好于16 ** n)。
–马丁·彼得斯(Martijn Pieters)♦
18年1月24日在13:41
#6 楼
更快,更轻松,更灵活的方法是使用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模块的作者。
#7 楼
从Python 3.6开始,如果需要加密而不是secrets
模块,则应使用random
模块(否则,此答案与@Ignacio Vazquez-Abrams的答案相同):from secrets import choice
import string
''.join([choice(string.ascii_uppercase + string.digits) for _ in range(N)])
注意:
str.join
的列表理解比使用生成器表达式要快!#8 楼
我以为还没有人回答这个大声笑!但是,嘿,这是我自己做的: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))], "")
评论
我不会对此表示反对,但是对于如此简单的任务,它太复杂了。返回表达式是一个怪物。简单胜于复杂。
–卡尔·史密斯
2012-12-28 23:14
@CarlSmith,是的,确实,我的解决方案似乎对这项任务有些矫kill过正,但是我知道其他更简单的解决方案,只是希望找到一条替代途径以获得良好答案。没有自由,创造力就处于危险之中,因此我继续发表。
–nemesisfixx
2012年12月29日下午4:40
#9 楼
根据另一个Stack Overflow答案,创建随机字符串和随机十六进制数的最轻巧的方法,比公认的答案更好的版本是:('%06x' % random.randrange(16**6)).upper()
更快。
评论
很好,尽管它只会使用“ A-F”而不是“ A-Z”。同样,当参数为N时,代码会变得不太好看。
–托马斯·阿勒
2014年1月29日,12:41
#10 楼
如果您需要随机字符串而不是伪随机字符串,则应使用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如何不是伪随机的?可能正在使用更好的算法来生成随机性更高的数字,但它仍然是伪随机的。
–提洛
2012年12月9日的15:00
@Tyilo,我知道/ dev / random和/ dev / urandom之间的区别。问题是/ dev / random在没有足够熵的情况下会阻塞,从而限制了它的有用性。暂时而言,/ dev / urandom不够好,但是我认为它比伪随机性好。
– John La Rooy
2012年12月9日在21:20
我会说/ dev / random和/ dev / urandom都是伪随机的,但这可能取决于您的定义。
–提洛
2012年12月9日在21:27
#11 楼
与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个字符串,randbit会丢失;)
除非我真的不会在生产代码中使用此方法不喜欢我的同事。
编辑:已更新为适合该问题(仅适用于大写字母和数字),并使用按位运算符&和>>代替%和//
#12 楼
我会这样: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) )
#13 楼
使用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/generation/ numpy.random.choice.html
评论
为什么我应该使用numpy random而不是python stdlib random?
– Pax0r
16年7月8日在13:17
因为它允许在参数中使用更多选项,例如长度,可变概率和带替换的选择。
–穆迪·贾恩(Mudit Jain)
16年7月11日在21:17
#14 楼
有时0(零)和O(字母O)可能会造成混淆。所以我用import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
#15 楼
>>> 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),它将不起作用
– MarSoft
16年1月9日在9:08
#16 楼
>>> 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'],但str = "".join(str)
照顾好了,让您留下'tm2JUQ04CK'
。希望有帮助!
评论
很好,但是您可以改用range(num),而str可以是字符串str + = random.choice(chars)。
– ashk
2014年5月9日16:32
#17 楼
对于那些喜欢使用功能性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))))
它会先生成一个随机选择符号的不确定序列,然后生成一个连接了随机序列的不确定[infinite]迭代器从给定池中,然后将此序列分解为多个长度部分,然后将其连接,它应该与支持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)
如果您不想使用next进行生成,则可以简单地将其生成可调用的:
>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> make_rand_tuples = partial(next, irand_tuples)
>>> make_rand_tuples()
(1, 6, 2, 8, 1, 9)
如果要动态生成序列,只需将join设置为identity。
>>> 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
即可提取下一个完全生成的块,当然这个例子似乎有点麻烦,而且... #18 楼
(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
#19 楼
这是对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()
#20 楼
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
评论
尽管此代码可以回答问题,但提供有关其为什么和/或如何回答问题的其他上下文将显着提高其长期价值。请编辑您的答案以添加一些说明。
– Toby Speight
16年5月11日在11:40
#21 楼
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循环中更改,即i在range(1,length)中
这是一种简单易懂的算法。它使用列表,因此您可以丢弃不需要的字符。
#22 楼
我正在寻找不同的答案,并花了一些时间阅读机密文档。机密模块用于生成适合于管理数据(例如密码,帐户身份验证,安全性令牌和相关秘密。
尤其是,应优先使用随机模块中默认的伪随机数生成器使用的秘密,该随机数生成器是为建模和仿真而设计的,而不是用于安全性或密码学的。
如果您想模仿诸如Google云端硬盘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的问题略有不同,但是我希望它对许多正在寻找相同用例的人仍然有帮助我一直在寻找的。
#23 楼
一个简单的例子: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
#24 楼
我想建议您下一个选择: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]
#25 楼
两种方法:br />
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))
第一种方法的性能更好。
#26 楼
我已经回答了几乎所有的答案,但是看起来都不容易。我建议您尝试通常用于创建随机密码的passgen库。您可以生成长度,标点,数字,字母和大小写选择的随机字符串。
这是您案例的代码:
from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')
#27 楼
生成随机的16字节ID包含字母,数字,'_'和'-'os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))
#28 楼
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
#29 楼
如果您想要一个易于使用但高度可定制的密钥生成器,请使用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
库。#30 楼
到目前为止,没有一个答案可以保证存在某些类别的字符,例如大写,小写,数字等。因此其他答案可能会导致密码中没有数字等。令人惊讶的是,该功能不是标准库的一部分。这是我使用的: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)
评论
这是一个非常受欢迎的问题。我希望专家可以对前3个答案的随机数的唯一性进行补充,即字符串大小范围(例如6到16)的碰撞概率。@buffer很容易计算出可能的组合数量。 10个数字+ 26个字母= 36个可能的字符,以6的幂(字符串的长度)大约等于20亿。对于随机值,我的经验法则是“如果我为地球上的每个人生成值,那么它们可以有多少个值?”。在这种情况下,每个人的值将小于一个值,因此,如果要识别用户或对象,则字符太少。一种选择是添加小写字母,使您的排名变为62 ^ 6 =几乎570亿唯一值。
尽管想想世界人口似乎很愚蠢,但这只是因为您想要一个巨大的缓冲来避免潜在的碰撞。请参阅生日问题:en.wikipedia.org/wiki/Birthday_problem
@buffer,那么您将对此答案感兴趣。
这不应该重命名为“加密安全的随机字符串生成...”吗?