关于Python的字符串生成一个随机的字母和数字上的案件

Random string generation with upper case letters and digits

我想生成一个大小为n的字符串。

它应该由数字和大写英文字母组成,例如:

  • 6U1S75
  • 4Z4UKK
  • U911K4

我怎样才能用Python的方式做到这一点?


一行回答:

1
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))

或者更简短,从使用random.choices()的python 3.6开始:

1
''.join(random.choices(string.ascii_uppercase + string.digits, k=N))

更安全的密码版本;请参阅https://stackoverflow.com/a/23728630/2213647:

1
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))

具体来说,具有清洁功能,可进一步重复使用:

1
2
3
4
5
6
7
8
9
>>> 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字符和数字的字符列表:

1
2
3
4
5
6
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

然后我们使用列表理解创建一个"n"元素列表:

1
2
3
4
>>> 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不会在内存中创建列表,而是一个接一个地动态生成元素(这里将详细介绍)。

我们不要求创建字符串elem的"n"倍,而是要求python创建随机字符"n"倍,从一系列字符中选取:

1
2
3
4
5
6
>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'

因此,random.choice(chars) for _ in range(size)实际上是在创建一个size字符序列。从chars中随机选取的字符:

1
2
3
4
5
6
>>> [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']

然后我们用一个空字符串将它们连接起来,这样序列就变成了一个字符串:

1
2
3
4
5
6
>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'


这个栈overflow的问题是目前的顶级谷歌的结果为"随机的Python字符串"。目前的顶级的答案是: </P >

1
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))

这是一个好的方法,但在随机产生器是不加密的安全。我假设这个问题,很多人researching威尔想要的杠杆随机字串的方法或加密的密码。你能做这securely法制作的小的变化,在上面的代码: </P >

1
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))

利用random.SystemRandom()去大学是随机使用的/ dev / urandom *nix是机器和CryptGenRandom()在Windows。这些都是密码安全的伪随机数发生器。利用random.choice去大学的random.SystemRandom().choice中的应用是一个安全的requires PRNG可能potentially devastating,和给定的问题,鲍比!本,我打赌那错误已被制造的时代已经很多了。 </P >

如果你是使用python3.6或以上,你可以使用新的保密模块。 </P >

1
''.join(secrets.choice(string.ascii_uppercase + string.digits) for _ in range(N))

该模块的文档也discuss convenient方式对杠杆的安全记录和最佳实践。 </P >


只需使用python的内置uuid:

如果UUID对于您的目的是可以的,请使用内置的UUID包。

一线解决方案:

import uuid; uuid.uuid4().hex.upper()[0:6]

深度版本:

例子:

1
2
3
import uuid
uuid.uuid4() #uuid4 => full random uuid
# Outputs something like: UUID('0172fc9a-1dac-4414-b88d-6b9a6feb91ea')

如果您需要正确的格式(例如"6U1S75"),可以这样做:

1
2
3
4
5
6
7
8
9
10
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,而不是分别选择每个字母,如果允许n次重复,则将随机基础扩大n倍,例如。

1
2
3
4
5
import random
import string

char_set = string.ascii_uppercase + string.digits
print ''.join(random.sample(char_set*6, 6))

注:sample防止字符重复使用,将字符集的大小相乘可以进行多次重复,但它们仍然比纯随机选择的可能性小。如果我们选择长度为6的字符串,并选择"x"作为第一个字符,在选择示例中,第二个字符获得"x"的几率与第一个字符获得"x"的几率相同。在random.sample实现中,作为任何后续字符获得"x"的几率只有第一个字符获得"x"的几率的6/7。


1
2
import uuid
lowercase_str = uuid.uuid4().hex

lowercase_str是一个类似'cea8b32e00934aaea8c005a35d85a5c0'的随机值。

1
uppercase_str = lowercase_str.upper()

uppercase_str'cea8b32e00934aaea8c005a35d85a5c0'


从Ignacio那里得到答案,这适用于python 2.6:

1
2
3
4
5
import random
import string

N=6
print ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))

实例输出:

JQUBT2


一种更快和更灵活的,easier通这样做是使用strgen模块(pip install StringGenerator)。 </P >

Generate a 6个字符的随机字符串与文学上的案例和位数: </P >

1
2
3
>>> from strgen import StringGenerator as SG
>>> SG("[\u\d]{6}").render()
u'YZI2CI'

得到一个独特的列表: </P >

1
2
>>> SG("[\l\d]{10}").render_list(5,unique=True)
[u'xqqtmi1pOk', u'zmkWdUr63O', u'PGaGcPHrX2', u'6RZiUbkk2i', u'j9eIeeWgEF']

担保的一个"特殊字符"中的字符串: </P >

1
2
>>> SG("[\l\d]{10}&[\p]").render()
u'jaYI0bcPG*0'

一个随机的HTML颜色: </P >

1
2
>>> SG("#[\h]{6}").render()
u'#CEdFCa'

等。 </P >

我们需要的是知道了那是这样的: </P >

1
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))

不可能有一个两位数的(或大写字符)在它。 </P >

strgen是更快的开发时间比任何以上的解决方案。在溶液中的fastest伊格纳西奥是运行时的表演和右键答案是使用Python标准库。但是你将永难使用在那形态。你会想要使用systemrandom(或fallback if不可用),让我相信所需的字符集是represented,使用Unicode(或不),让我相信迭代调用产生一个独特的字符串,使用A的子集的一部模块的字符串的字符类,等。这全requires很多更多的代码比在答案库提供的。在各种不同的尝试到generalize A溶液全有局限性,strgen解决与大brevity和expressive功率使用一种简单的模板语言。 </P >

它是pypi页: </P >

1
pip install StringGenerator

信息披露:I’m的作者的strgen模块。 </P >


我还以为没人回答这个呢,哈哈!但是,嘿,这是我自己的行动:

1
2
3
4
5
6
7
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作为源。

1
2
3
4
5
6
7
8
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))


基于另一个堆栈溢出答案(创建随机字符串和随机十六进制数的最轻方法),比公认答案更好的版本是:

1
('%06x' % random.randrange(16**6)).upper()

快得多。


与发布的random.choice()方法ignacio相比,此方法速度稍快,也稍有烦人。

它利用了伪随机算法的特性,并且按位和移位排列比为每个字符生成新的随机数更快。

1
2
3
4
5
6
7
8
9
10
# 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()生成器对具有正确位的随机数的结果

对于32个字符串,时间是:

1
2
[('generate_with_random_choice', 28.92901611328125),
 ('generate_with_randbits', 20.0293550491333)]

…但是对于64个字符串,randbits会丢失;)

我可能永远不会在生产代码中使用这种方法,除非我真的不喜欢我的同事。

编辑:更新以适应问题(仅大写和数字),并使用位运算符&;and>>而不是%and//


从python 3.6开始,如果需要使用加密安全的secrets模块而不是random模块,则应使用该模块(否则,此答案与@ignacio vazquez abrams中的一个相同):

1
2
3
4
from secrets import choice
import string

''.join([choice(string.ascii_uppercase + string.digits) for _ in range(N)])

另外一个注意事项:在str.join的情况下,列表理解比使用生成器表达式更快!


我会这样做:

1
2
3
4
5
6
7
8
9
10
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

或者只是:

1
2
3
def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )

1
2
>>> import string
>>> import random

下面的逻辑仍然generates 6个字符的随机抽样 </P >

1
2
>>> print ''.join(random.sample((string.ascii_uppercase+string.digits),6))
JT7K3Q

我需要multiply×6 </P >

1
2
3
>>> print ''.join(random.sample((string.ascii_uppercase+string.digits)*6,6))

TK82HK


使用numpy的random.choice()函数

1
2
3
4
5
6
7
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


为那些你谁enjoy Python的功能: </P >

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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))))

它generates安indefinite [ ]无限的迭代器,joined随机序列,通过序列生成一indefinite第一部randomly选定的符号,从给池,然后破这件长度的序列的热情,这是当时的joined,它应该与工作的任何序列的那支getitem by default,它是generates随机序列的大学有一个数值的信,不过你可以轻易地修改的杠杆:其他的事情。 </P >

for example to Generate随机位的重复速率元组): </P >

1
2
3
4
5
>>> 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)

如果你不想使用下一代的方法是你可以做的callable: </P >

1
2
3
4
>>> irand_tuples = irand_seqs(xrange(10), join=tuple)
>>> make_rand_tuples = partial(next, irand_tuples)
>>> make_rand_tuples()
(1, 6, 2, 8, 1, 9)

如果你想在Generate序列是飞,是集我的身份。 </P >

1
2
3
4
5
6
>>> irand_tuples = irand_seqs(xrange(10), join=identity)
>>> selections = next(irand_tuples)
>>> next(selections)
8
>>> list(selections)
[6, 3, 8, 2, 2]

为他人有这些,如果你需要更多的安全和适当的函数集的选择: </P >

1
2
3
>>> from random import SystemRandom
>>> rand_strs = irand_seqs(select=SystemRandom().choice)
'QsaDxQ'

在默认的电动打字机是choice这可能选择同样的符号的多中心时代的每一块,如果你想要的,而不是D的同一人的选择,在一次最为每一块,那么,一个可能的使用: </P >

1
2
3
4
>>> 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这fetches化外,生下一块,以granted这看来,一位cumbersome和它是………………… </P >


(1)这将给您所有的上限和数字:

1
2
3
4
5
6
7
8
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)如果您以后希望在密钥中包含小写字母,那么这也将有效:

1
2
3
4
5
6
7
8
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的回应和我自己正在做的事情的一个看法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 +"
"
)
oneFile.close()

1
2
3
4
5
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


1
2
3
4
5
6
7
8
9
10
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在范围(1,长度)中更改。算法简单易懂。它使用list,这样您就可以丢弃不需要的字符。


1
2
3
4
5
6
7
8
9
10
11
>>> 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函数picks随机输入在一个列表中。你也创建一个列表,所以你可以append的字符在forstatement。在年底的STR是["T","M","2","J","U","Q","0","4","C","D"],但str ="".join(str)把照顾那,离开你和'tm2JUQ04CK'。。。。。。。 </P >

希望这helps!!!!!!! </P >


一个简单的一个: </P >

1
2
3
4
5
6
7
8
9
10
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

几乎所有的答案我都看过了,但没有一个看起来更简单。我建议您尝试使用passgen库,它通常用于创建随机密码。

您可以生成任意长度、标点、数字、字母和大小写的字符串。

这是您的案例代码:

1
2
3
from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')

我建议你下一个选择:

1
2
3
import crypt
n = 10
crypt.crypt("any sring").replace('/', '').replace('.', '').upper()[-n:-1]

偏执模式:

1
2
3
4
import uuid
import crypt
n = 10
crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1]


两种方法:

1
import random, math

1
2
3
4
5
6
7
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)

1
2
def randStr_2(chars:str, length:int) -> str:
    return ''.join(random.choice(chars) for i in range(chars))

< BR>

Benchmark :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 = {} : {}
'
.format(eff1/eff1, round(eff2/eff1, 2)))

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

第一种方法的性能更好。


对于Python 3导入字符串,随机

'.join(random.choice(string.ascii_小写+string.ascii_大写+string.digits),用于范围(15)内的


我发现这个更简单更干净。

1
2
3
4
5
6
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来改变长度,改变字符池来做字母-数字或数字-唯一或奇怪的字符或任何你想要的。


你可以用密码

1
2
3
4
5
6
7
8
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更改为您希望的任何数字,它将产生如此多的数字和/或字母。

写这个的另一种方法是…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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"。如果有人知道如何限制结果具有此类限制,请回复评论。