在Python中用大写字母和数字随机生成string
我想要生成一个大小为N的string
它应该由数字和大写英文字母组成,例如:
- 6U1S75
- 4Z4UKK
- U911K4
我怎样才能达到这pythonic的方式?
一行回答:
''.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))
密码更安全的版本; 请参阅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'
它是如何工作的 ?
我们inputstring
,一个包含常用ASCII字符序列的模块, random
一个处理随机生成的模块。
string.ascii_uppercase + string.digits
只是连接代表大写ASCII字符和数字的字符列表:
>>> string.ascii_uppercase 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' >>> string.digits '0123456789' >>> string.ascii_uppercase + string.digits 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
然后,我们使用列表理解来创build“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']
在上面的例子中,我们使用[
创build列表,但是我们不在id_generator
函数中,所以Python不会在内存中创build列表,而是一个接一个地生成元素( 这里更详细的介绍) 。
我们不会要求创buildstringelem
“n”次,而是要求Python创build一个随机字符“n”,从字符序列中挑选出来:
>>> random.choice("abcde") 'a' >>> random.choice("abcde") 'd' >>> random.choice("abcde") 'b'
因此random.choice(chars) for _ in range(size)
实际上是创build一个size
字符序列。 从chars
中随机选取的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']
然后我们只需要用一个空string连接它们,这样序列就变成了一个string
>>> ''.join(['a', 'b', 'b']) 'abb' >>> [random.choice('abcde') for _ in range(3)] ['d', 'c', 'b'] >>> ''.join(random.choice('abcde') for _ in range(3)) 'dac'
这个堆栈溢出quesion是目前谷歌“随机stringPython”的结果。 目前最高的答案是:
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
这是一个很好的方法,但随机PRNG不是密码安全的。 我想很多人研究这个问题将要产生随机stringencryption或密码。 你可以通过在上面的代码中做一些小改动来安全地做到这一点:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
使用random.SystemRandom()
而不是随机在* nix机器上使用/ dev / urandom和在Windows中使用CryptGenRandom()
。 这些是密码安全的PRNG。 在需要安全PRNG的应用程序中使用random.choice
而不是random.SystemRandom().choice
可能具有破坏性,考虑到这个问题的普及,我敢打赌已经犯了很多错误。
只需使用Python的内置uuid:
如果UUID适合您的用途,请使用内置的uuid软件包。
一线解决scheme:
import uuid; str(uuid.uuid4().get_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
而不是分别select每个字母,如果允许n次重复,则将您的随机基数扩大n倍。
import random import string char_set = string.ascii_uppercase + string.digits print ''.join(random.sample(char_set*6, 6))
注意:random.sample防止字符重用,乘以字符集的大小使得多次重复成为可能,但是它们仍然不太可能,那么它们是纯粹的随机select。 如果我们input一个长度为6的string,并且select'X'作为第一个字符,那么在select示例中,获得'X'的第二个字符的可能性与得到'X'的可能性相同第一个字符。 在random.sample实现中,获取'X'作为任何后续字符的几率只有6/7的机会,作为第一个字符
更快,更简单,更灵活的方法是使用strgen
模块( pip install StringGenerator
)。
用大写字母和数字生成一个6个字符的随机string:
>>> 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']
在string中保证一个“特殊”字符:
>>> 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))
可能没有数字(或大写字符)。
开发时间比上述任何解决scheme都快。 Ignacio的解决scheme是运行速度最快的解决scheme,使用Python标准库是正确的select。 但是你几乎不会以这种forms使用它。 您将需要使用SystemRandom(或者如果不可用则使用回退),确保所需的字符集被表示,使用unicode(或不),确保连续的调用产生一个唯一的string,使用一个string模块字符类的子集,这一切都需要更多的代码比提供的答案。 概括解决scheme的各种尝试都有一些局限性,即使用简单的模板语言,strgen解决更大的简洁性和performance力。
在PyPI上:
pip install StringGenerator
披露:我是strgen模块的作者。
import uuid str = uuid.uuid4().hex
str
是一个随机值,如'cea8b32e00934aaea8c005a35d85a5c0'
uppercase_str = 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
如果你需要一个随机的string,而不是一个伪随机的 ,你应该使用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))
我以为没有人回答这个问题呢! 但是,嘿,这是我自己去的:
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))], "")
基于另一个堆栈溢出的答案, 最轻量级的方式来创build一个随机的string和一个随机的hex数字 ,比接受的答案更好的版本将是:
('%06x' % random.randrange(16**6)).upper()
快多了。
这个方法比Ignacio发布的random.choice()方法稍微快一点,更麻烦一些。
它利用了伪随机algorithm的性质,对每个字符产生一个新的随机数,按位和移位的存储速度要快。
# 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')
…创build一个发生器,在0..31时间内取出5位数字,直到没有剩下的数字
…用正确的位连接()发生器的结果在一个随机数上
有了Timeit,对于32个字符的string,时间是:
[('generate_with_random_choice', 28.92901611328125), ('generate_with_randbits', 20.0293550491333)]
…但是对于64个字符的string,randbits失去了;)
除非我真的不喜欢我的同事,否则我绝不会在生产代码中使用这种方法。
编辑:更新以适应问题(仅限大写和数字),并使用按位运算符&和>>代替%和//
从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
的情况下,列表理解的速度要快于使用生成器expression式!
我会这样做:
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) )
对于那些喜欢function性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))))
它通过首先从给定池中随机select的符号生成一个不确定的序列,然后将这个序列分解成长度部分然后连接起来,产生一个不确定的[无限]迭代器,它是连接随机序列的,它应该支持任何支持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]
正如其他人所提到的,如果您需要更多的安全性,请设置相应的selectfunction
>>> from random import SystemRandom >>> rand_strs = irand_seqs(select=SystemRandom().choice) 'QsaDxQ'
默认select器是可以为每个块select相同符号多次的select,但是如果您希望每个块最多select一个相同的成员,那么可以使用一个可能的用法:
>>> 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
作为我们的select器,做完整的select,所以块实际上是长度为1,并join我们只需调用next
获取下一个完全生成的块,授予这个例子似乎有点繁琐,它是…
(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()
使用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
>>> 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
函数在列表中选取一个随机条目。 您还可以创build一个列表,以便您可以在for
语句中附加该字符。 最后str是['t','m','2','J','U','Q','0','4','C','K'],但str = "".join(str)
照顾到这一点,给你留下'tm2JUQ04CK'
。
希望这可以帮助!
一个简单的:
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
导入string导入随机
下面的逻辑仍然会产生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
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
我想build议你下一个选项:
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]
我发现这是更简单和更清洁。
str_Key = "" str_FullKey = "" str_CharacterPool = "01234ABCDEFfghij~>()" for int_I in range(64): str_Key = random.choice(str_CharacterPool) str_FullKey = str_FullKey + str_Key
只要改变64来改变长度,改变CharacterPool做alpha只字母数字或数字或奇怪的字符或任何你想要的。
你可以使用代码
var chars = "ABC123"; var random = new Random(); var result = new string( Enumerable.Repeat(chars, 7) //Change 7 to any number of characters you want in your outcome .Select(s => s[random.Next(s.Length)]) .ToArray()); textBox1.Text = result;
这将随机吐出一个随机的7个字母数字模式,只需将7更改为您希望的任何数字,它将产生许多数字和/或字母。
另一种方式来写这个如下…
var chars = "ABC123"; var stringChars = new char[7]; //Change 7 to any number of characters you want in your outcome var random = new Random(); for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } var finalString = new String(stringChars); textBox1.Text = finalstring;`
我不确定如何添加限制,例如,如果有人知道如何限制结果有类似的东西,使它不允许某些数字和/或字母彼此相邻或重复,如获得“AAA123”这个请回复