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
_
しかし、私は両方が好きではありません:
i
変数があり、それを回避する良い方法が見つかりませんだから、他の良いオプションはありますか?
追伸そのため、ここではtimeit
を使用した100000回の反復テストを行っています。
_''.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
_
したがって、勝者は''.join(choice(chars) for _ in xrange(length))
です。
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
暗号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))
均等な分布では、chars
文字列の長さは128の整数の除数である必要があります。そうでない場合は、スペースから均一に選択する別の方法が必要になります。
[〜#〜] warning [〜#〜]重大なセキュリティ問題のため、この回答は無視する必要があります!
オプション#2は、いくつかの改善点を追加できることを除いて、かなり合理的です。
''.join(choice(chars) for _ in range(length)) # in py2k use xrange
_
は従来の「そこに何があるかは気にしない」変数です。そこにリストを理解する必要はありません。ジェネレーター式はstr.join
。また、それが唯一のcorrect方法である場合、「遅い」が何を意味するかも明確ではありません。
これでうまくいくと思います。 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)
python <3.6:
import os, math, string, struct
def generate_password(pass_len):
symbols = string.printable.strip()
return ''.join([symbols[x * len(symbols) / 256] for x in struct.unpack('%dB' % (pass_len,), os.urandom(pass_len))])
これには、Ben Mosherのソリューションに勝る利点があります。これは、シンボルからの各シンボルの発生が均等に変化するのに対し、モジュラスを使用すると、アルパベットの最初のシンボルがわずかに優先されるためです。この提案では、記号のアルファベットも大きくなっています。