我想在python中生成一些字母数字密码.一些可能的方法是:
import string
from random import sample, choice
chars = string.letters + string.digits
length = 8
''.join(sample(chars,length)) # way 1
''.join([choice(chars) for i in range(length)]) # way 2
Run Code Online (Sandbox Code Playgroud)
但我不喜欢两者,因为:
i变量未使用,我找不到如何避免这种情况的好方法那么,还有其他好的选择吗?
PS所以这里我们正在进行一些timeit100000次迭代的测试:
''.join(sample(chars,length)) # way 1; 2.5 seconds
''.join([choice(chars) for i in range(length)]) # way 2; 1.8 seconds (optimizer helps?)
''.join(choice(chars) for _ in range(length)) # way 3; 1.8 seconds
''.join(choice(chars) for _ in xrange(length)) # way 4; 1.73 seconds
''.join(map(lambda x: random.choice(chars), range(length))) # way 5; 2.27 seconds
Run Code Online (Sandbox Code Playgroud)
所以,获胜者是''.join(choice(chars) for _ in xrange(length)).
ger*_*rit 92
您应该使用secrets模块生成加密安全密码,从Python 3.6开始提供.改编自文档:
import secrets
import string
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(20)) # for a 20-character password
Run Code Online (Sandbox Code Playgroud)
Ben*_*her 33
对于那里的加密PRNG人员:
def generate_temp_password(length):
if not isinstance(length, int) or length < 8:
raise ValueError("temp password must have positive length")
chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
from os import urandom
return "".join(chars[ord(c) % len(chars)] for c in urandom(length))
Run Code Online (Sandbox Code Playgroud)
注意,对于均匀分布,chars字符串长度应该是128的整数除数; 否则,你需要一种不同的方式从空间中统一选择.
Sil*_*ost 13
警告由于严重的安全问题,应忽略此答案!
选项#2似乎很合理,除了你可以添加一些改进:
''.join(choice(chars) for _ in range(length)) # in py2k use xrange
Run Code Online (Sandbox Code Playgroud)
_是一个传统的"我不在乎那里有什么"变量.而且你不需要那里的列表理解,生成器表达式就可以了str.join.如果它是唯一正确的方法,也不清楚"慢"意味着什么.
np8*_*np8 10
使用内置秘密的两个食谱(python 3.6+)
这比接受的答案要快得多。(见下面的时间)
import secrets
password = secrets.token_urlsafe(32)
Run Code Online (Sandbox Code Playgroud)
示例输出:
4EPn9Z7RE3l6jtCxEy7CPhia2EnYDEkE6N1O3-WnntU
Run Code Online (Sandbox Code Playgroud)
的参数token_urlsafe是字节数。平均而言,一个字节是 1.3 个字符(base64 编码)。
这是从秘密文档中略加修改的副本。有了这个,您可以更精细地控制如何生成密码。当然,如果您需要生成大量密码,这不是一个快速的选择。
alphabet. 在这个例子中,有 just-和_added。4EPn9Z7RE3l6jtCxEy7CPhia2EnYDEkE6N1O3-WnntU
Run Code Online (Sandbox Code Playgroud)
示例输出:
HlxTm2fcFE54JA1I_Yp5
Run Code Online (Sandbox Code Playgroud)
如果考虑速度,您还可以删除 while 循环。在这种情况下,它实际上简化了 gerrit 的答案(但随后您失去了更细粒度的控制):
import string
import secrets
alphabet = string.ascii_letters + string.digits + '-_'
while True:
password = ''.join(secrets.choice(alphabet) for i in range(20))
if (sum(c.islower() for c in password) >=4
and sum(c.isupper() for c in password) >=4
and sum(c.isdigit() for c in password) >=4):
break
Run Code Online (Sandbox Code Playgroud)
1.secrets.token_urlsafe
1.62 µs ± 96.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Run Code Online (Sandbox Code Playgroud)
2.强制执行数字/大写字符等
107 µs ± 11.9 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)
3.“我不需要更细粒度的控制”
77.2 µs ± 9.31 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)
速度比较设置:Win10 上的 python 3.8.5 64 位,每个密码 43 个字符(= 32 字节的 token_urlsafe)。
我想这就行了.random.SystemRandom使用相同的底层加密随机函数,os.urandom但它使用熟悉的random界面.这个函数不会像Ben的答案那样受到奇怪的128字节的影响.
import random
import string
def gen_random_string(char_set, length):
if not hasattr(gen_random_string, "rng"):
gen_random_string.rng = random.SystemRandom() # Create a static variable
return ''.join([ gen_random_string.rng.choice(char_set) for _ in xrange(length) ])
password_charset = string.ascii_letters + string.digits
gen_random_string(password_charset, 32)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43449 次 |
| 最近记录: |