Генерация случайной строки с заглавными буквами и цифрами - PullRequest
1187 голосов
/ 13 февраля 2010

Я хочу сгенерировать строку размером N.

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

  • 6U1S75
  • 4Z4UKK
  • U911K4

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

Ответы [ 27 ]

2336 голосов
/ 13 февраля 2010

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

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

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

Мы импортируем 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'
516 голосов
/ 19 мая 2014

Этот вопрос о переполнении стека является текущим лучшим результатом 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))

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

167 голосов
/ 26 июня 2013

Просто используйте встроенный в 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
44 голосов
/ 13 февраля 2010

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

30 голосов
/ 01 декабря 2015
import uuid
lowercase_str = uuid.uuid4().hex  

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

uppercase_str = lowercase_str.upper()

uppercase_str - это 'CEA8B32E00934AAEA8C005A35D85A5C0'

19 голосов
/ 26 августа 2014

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

10 голосов
/ 19 декабря 2013

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

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

намного быстрее.

9 голосов
/ 04 января 2017

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

9 голосов
/ 13 сентября 2012

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

Я думал, что никто еще не ответил на это, лол! Но эй, вот мой собственный взгляд на это:

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