Генерация случайной строки с заглавными буквами и цифрами

Я хочу создать строку размера N.

Он должен состоять из цифр и прописных английских букв, например:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Как я могу достичь этого в pythonic?

Ответы

Ответ 1

Ответ в одной строке:

''.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))

Криптографически более безопасная версия; см. fooobar.com/questions/11498/...:

''.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'

Как это работает?

Мы импортируем string, модуль, который содержит последовательности общих символов ASCII и 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 не создает список в памяти, а генерирует элементы "на лету", один на один (подробнее об этом здесь).

Вместо того, чтобы просить создать "n" раз строку elem, мы попросим 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'

Ответ 2

Этот вопрос Qaru является текущим лучшим результатом Google для "случайной строки Python". Текущий топ-ответ:

''.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() вместо случайного использования /dev/urandom на машинах * nix и CryptGenRandom() в Windows. Это криптографически безопасные PRNG. Использование random.choice вместо random.SystemRandom().choice в приложении, которое требует защищенного PRNG, может быть потенциально разрушительным, и, учитывая популярность этого вопроса, держу пари, что ошибка уже была совершена много раз.

Если вы используете python3.6 или выше, вы можете использовать новый секретный модуль, как упомянуто в ответе MSeifert:

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

В модуле также обсуждаются удобные способы создания безопасных токенов и рекомендации.

Ответ 3

Просто используйте Python, встроенный в uuid:

Если UUID подходят для ваших целей, используйте встроенный пакет uuid.

Решение One Line:

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

Ответ 4

Более простой, быстрый, но немного менее случайный способ заключается в использовании random.sample вместо того, чтобы выбирать каждую букву отдельно. Если n-повторений разрешено, увеличьте свою случайную основу на n раз, например.

import random
import string

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

Примечание: random.sample предотвращает повторное использование символов, умножая размер набора символов делает возможным несколько повторений, но они все же менее вероятны, тогда они находятся в чисто случайном выборе. Если мы идем для строки длиной 6, и мы выбираем "X" в качестве первого символа, в примере выбора шансы получить "X" для второго символа совпадают с шансами получить "X" в качестве первый символ. В реализации random.sample шансы получить "X" в качестве любого последующего символа - это только 6/7 шанс получить его как первый символ

Ответ 5

import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str - это случайное значение, например 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str является 'CEA8B32E00934AAEA8C005A35D85A5C0'

Ответ 6

Принимая ответ от Ignacio, это работает с Python 2.6:

import random
import string

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

Пример вывода:

JQUBT2

Ответ 7

Более быстрый, простой и гибкий способ сделать это - использовать модуль 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']

Гарантия одного "специального" символа в строке:

>>> 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 (или использовать запасной вариант, если он недоступен), убедиться, что требуемые наборы символов представлены, использовать юникод (или нет), убедиться, что последовательные вызовы создают уникальную строку, использовать подмножество одного из классов символов модуля строки, и т.д. Все это требует гораздо больше кода, чем в ответах. Различные попытки обобщить решение имеют ограничения, которые strgen решает с большей краткостью и выразительностью, используя простой язык шаблонов.

Это на PyPI:

pip install StringGenerator

Раскрытие информации: я являюсь автором модуля strgen.

Ответ 9

Из 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 понимание списка выполняется быстрее, чем использование выражения генератора!

Ответ 10

Я думал, никто не ответил на это, но LOL! Но эй, здесь мои собственные идут на это:

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))], "")

Ответ 11

Если вам нужна случайная строка, а не псевдослучайная, вам следует использовать 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))

Ответ 12

Этот метод немного быстрее и немного более раздражает, чем метод random.choice(), отправленный Ignacio.

Он использует природу псевдослучайных алгоритмов, а банки поразрядного и сдвига быстрее, чем генерация нового случайного числа для каждого символа.

# 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 теряет;)

Я бы, вероятно, никогда не использовал этот подход в производственном кодексе, если бы я действительно не любил своих сотрудников.

изменить: обновить в соответствии с вопросом (только в верхнем регистре и только цифры) и использовать побитовые операторы и → вместо% и//

Ответ 13

Я бы сделал это следующим образом:

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) )

Ответ 14

>>> 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

Ответ 16

Для тех, кто любит функциональный питон:

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))))

Он генерирует неопределенный [бесконечный] итератор объединенных случайных последовательностей, сначала создавая неопределенную последовательность случайно выбранного символа из пула отдачи, затем разбивая эту последовательность на части длины, которые затем соединяются, она должна работать с любой последовательностью который поддерживает 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]

Как уже упоминалось, если вам нужна дополнительная безопасность, установите соответствующую функцию выбора:

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

селектор по умолчанию choice, который может выбирать один и тот же символ несколько раз для каждого фрагмента, если вместо этого вы хотите, чтобы один и тот же член был выбран не более одного раза для каждого фрагмента, то одно из возможных использования:

>>> 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, который извлекает следующий полностью сгенерированный фрагмент, предоставленный этому примеру, кажется немного громоздким и это...

Ответ 17

(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  

Ответ 18

это взятие ответа 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()

Ответ 19

>>> 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'.

Надеюсь, это поможет!

Ответ 20

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

Ответ 21

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, т.е. для я в диапазоне (1, длина). Это простой алгоритм, который легко понять. он использует список, так что вы можете отказаться от символов, которые вам не нужны.

Ответ 22

Иногда 0 (ноль) и O (буква O) могут сбивать с толку. Поэтому я использую

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')

Ответ 23

Простой:

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

Ответ 24

Я хотел бы предложить вам следующий вариант:

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]

Ответ 25

Два метода:

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

Производительность первого метода лучше.

Ответ 26

для Python 3 строка импорта, случайная

''.join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) для _ в диапазоне (15))

Ответ 27

from random import choice
length = 16 # Insert your own length here.
string=''
for i in range(1,length):
    j=choice('A','B','C') # Fill this list with all the characters the string is made of.
    string=join(string,j)
print(string)

Ответ 28

Я пошел, хотя почти все ответы, но ни один из них не выглядит проще. Я бы посоветовал вам попробовать библиотеку passgen, которая обычно используется для создания случайных паролей.

Вы можете генерировать случайные строки на ваш выбор длины, пунктуации, цифр, букв и регистра.

Вот код для вашего случая:

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

Ответ 29

Я нашел это более простым и чистым.

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, чтобы делать только альфа-числовые или числовые буквы или странные символы или что угодно.

Ответ 30

Вы можете использовать код

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", если кто-либо знает, как ограничить результат есть что-то вроде этого, пожалуйста, прокомментируйте