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))
暗号的に安全なバージョン。 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'
どのように機能しますか?
一般的なASCII文字のシーケンスを含むモジュールstring
と、ランダム生成を処理するモジュール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はメモリ内にリストを作成しませんが、実行中の要素を1つずつ(詳細については こちら )。
文字列elem
を 'n'回作成する代わりに、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'
このスタックオーバーフローの問題は、 "ランダムな文字列の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が、WindowsではCryptGenRandom()
が使用されます。これらは暗号的に安全なPRNGです。安全なPRNGを必要とするアプリケーションでrandom.SystemRandom().choice
の代わりにrandom.choice
を使用することは潜在的に壊滅的である可能性があり、この質問の人気を考えると、私は間違いが既に何度もなされたことを確信します。
Python3.6以上を使っているなら、new secrets モジュールを使うことができます。
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))
モジュールのドキュメントでは 安全なトークンを生成するための便利な方法についても議論しています と ベストプラクティス 。
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
より簡単で、速いがわずかにランダムではない方法は、各文字を別々に選択する代わりにrandom.sample
を使用することです。
import random
import string
char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))
注:random.sampleは文字の再利用を防ぎ、文字セットのサイズを掛けることで複数の繰り返しが可能になりますが、それでもそれらが純粋にランダムに選択される可能性は低いです。長さ6の文字列を検索し、最初の文字として 'X'を選択した場合、選択例では、2番目の文字として 'X'を取得する確率は、最初の文字として 'X'を取得する確率と同じです。最初の文字random.sampleの実装では、後続の文字として 'X'を取得する可能性は6/7ですが、最初の文字として取得する可能性はわずかです。
import uuid
lowercase_str = uuid.uuid4().hex
lowercase_str
は'cea8b32e00934aaea8c005a35d85a5c0'
のようなランダムな値です
uppercase_str = lowercase_str.upper()
uppercase_str
は'CEA8B32E00934AAEA8C005A35D85A5C0'
です
Ignacioから答えを取って、これはPython 2.6で動作します:
import random
import string
N=6
print ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
出力例
JQUBT2
これを行うより速く、より簡単で、より柔軟な方法は 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']
保証 文字列内の1つの "特殊"文字
>>> 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モジュールの作者です。
別のStack Overflowの回答に基づいて、ランダムな文字列とランダムな16進数を作成するための最も軽量な方法。
('%06x' % random.randrange(16**6)).upper()
はるかに高速。
私は誰もまだこれに答えていないと思いました(笑)しかし、ねえ、これが私自身のやり方です。
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))], "")
擬似乱数 の代わりにランダムな文字列が必要な場合は、ソースとして 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))
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)])
もう1つ注意してください:str.join
の場合、ジェネレータ式を使用するよりもリスト内包表記の方が高速です。
このメソッドは、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')
... 5ビット数を一度に0から31まで取り去るジェネレータを作成する
...正しいビットを持つ乱数に対するジェネレータの結果をjoin()する
Timeitでは、32文字の文字列の場合、タイミングは次のとおりです。
[('generate_with_random_choice', 28.92901611328125),
('generate_with_randbits', 20.0293550491333)]
...しかし64文字の文字列の場合、randbitsは失います;)
私が同僚を本当に嫌いでない限り、私はおそらく本番コードでこのアプローチを決して使用しないでしょう。
edit:質問に合わせて更新され(大文字と数字のみ)、%と//ではなくビット演算子&と>>が使用されます。
私はこうします:
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) )
Numpyのrandom.choice()関数を使う
import numpy as np
import string
if __== '__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
>>> 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
(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
これは、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()
機能的な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))))
与えられたプールからランダムに選択されたシンボルの不定シーケンスを生成し、次にこのシーケンスを長さの部分に分割して結合することによって、結合されたランダムシーケンスの無限(無限)反復子を生成します。デフォルトでは、英数字のランダムなシーケンスを生成するだけですが、他のものを生成するように簡単に変更できます。
たとえば、数字のランダムなタプルを生成するには、
>>> 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
で、これは各チャンクに対して同じシンボルを複数回選択することができます。代わりに、同じチャンクに対して同じメンバーをせいぜい1回選択したい場合は、1つの使用法があります。
>>> 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
を呼び出します。
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(i、length)に変更することができます。分かりやすい単純なアルゴリズムです。リストを使用するので、不要な文字は破棄できます。
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
簡単なもの:
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
>>> 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'
であなたを残して、その世話をします。
お役に立てれば!
私はほとんどすべての答えを見てきましたが、どれも簡単には見えません。ランダムなパスワードを作成するために一般的に使用されている passgen ライブラリを試すことをお勧めします。
長さ、句読点、数字、文字 および caseを選択して、ランダムな文字列を生成できます。
これがあなたの場合のコードです。
from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')
2つの方法:
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
最初の方法のパフォーマンスは優れています。
次の選択肢を提案します。
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]
時には0(ゼロ)とO(文字O)が混乱を招くことがあります。だから私は使う
import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
python 3のインポート文字列、ランダム
'' .join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits)(範囲(15)の_の場合))