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

1338

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

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

  • 6U1S75
  • 4Z4UKK
  • U911K4

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

Hellnar
источник
11
Это очень популярный вопрос. Я хотел бы, чтобы эксперт добавил свое мнение об уникальности этих случайных чисел для первых трех ответов, то есть вероятности столкновения для диапазона размера строки, скажем, от 6 до 16.
пользователь
8
@buffer Легко рассчитать количество возможных комбинаций. 10 цифр + 26 букв = 36 возможных символов, степень 6 (длина строки) равна примерно двум миллиардам. Мое эмпирическое правило для случайных значений: «Если бы я генерировал значения для каждого человека на Земле, сколько значений они могли бы иметь у каждого?». В этом случае это будет меньше, чем одно значение на человека, поэтому, если это для идентификации пользователей или объектов, это слишком мало символов. Один из вариантов - добавить строчные буквы, и вы получите 62 ^ 6 = почти 57 миллиардов уникальных значений.
Blixt
1
И хотя может показаться глупым думать о населении мира, это просто потому, что вы хотите огромный буфер для потенциальных столкновений. Смотрите проблему дня рождения: en.wikipedia.org/wiki/Birthday_problem
Blixt
1
@buffer, вас бы тогда заинтересовал этот ответ .
Аниш Рамасвами
Разве это не должно быть переименовано в «Криптографически безопасная генерация случайных строк ...» ?
SMCI

Ответы:

2544

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

''.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'
Игнасио Васкес-Абрамс
источник
7
@jorelli: Это не понимание списка; это выражение генератора.
Игнасио Васкес-Абрамс
2
@joreilli: я добавил в ответ краткую заметку об этом и ссылку на более подробный ответ о повторяемости, понимании списка, генераторах и, в конечном итоге, ключевом слове yield.
е-сат
1
Я бы заменил rangeна xrange.
Доктор Ян-Филипп Герке
1
Очень полезный. Интересно, что Django использует этот кусок кода для генерации паролей и токенов CSRF. Хотя вы должны заменить randomна random.SystemRandom(): github.com/django/django/blob/…
пользователь
1
@ Chiel92, random.sampleсоздает образцы без замены, другими словами, без возможности повторения символов, что не соответствует требованиям ОП. Я не думаю, что это было бы желательно для большинства приложений.
онтолог
557

Этот вопрос переполнения стека является текущим лучшим результатом 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
Да, официальная стандартная библиотека for randomпредупреждает это: « Предупреждение : генераторы псевдослучайных чисел этого модуля не должны использоваться в целях безопасности. Используйте os.urandom () или SystemRandom, если вам требуется криптографически безопасный генератор псевдослучайных чисел. " Вот ссылка: random.SystemRandom и os.urandom
lord63. J
4
Отличный ответ. Небольшое примечание: Вы изменили его, string.uppercaseчто может привести к неожиданным результатам в зависимости от установленного языкового стандарта. Использование string.ascii_uppercase(или string.ascii_letters + string.digitsдля base62 вместо base36) более безопасно в случаях, когда используется кодирование.
Blixt
небольшая заметка - лучше использовать xrangeвместо того, rangeчтобы последний генерировал список в памяти, тогда как первый создает итератор.
Гайарад
2
случайный укус всегда будет уникальным? Я хотел использовать первичный ключ.
Shakthydoss
3
@shakthydoss: нет. Он может возвращать «AAA000», которая является случайной строкой, и следующий «AAA000», который также является случайной строкой. Вы должны явно добавить проверку на уникальность.
usr2564301
189

Просто используйте встроенный в 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
Bijan
источник
14
+1 Для размышлений за вопросом. Возможно, вы могли бы кратко объяснить разницу между uuid1 и uuid4.
Томас Ахле
1
Если я выполняю uuid1 три раза подряд, я получаю: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8, которые все кажутся похожими первые 8 символов различаются, а остальные одинаковы). Это не относится к uuid4
Чейз Робертс
9
uui1: сгенерируйте UUID из идентификатора хоста, порядкового номера и текущего времени. uuid4: создать случайный UUID.
Биджан
7
Если вы хотите пропустить приведение строки и замену дефиса, вы можете просто вызвать my_uuid.get_hex () или uuid.uuid4 (). Get_hex (), и он вернет строку, сгенерированную из uuid, в которой нет дефисов.
dshap
8
Это хорошая идея, чтобы обрезать UUID? В зависимости от того, насколько мала string_length, вероятность столкновения может быть проблемой.
пользователь
44

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

Анураг Униял
источник
8
Этот способ неплох, но он не такой случайный, как выбор каждого символа в отдельности, так как sampleвы никогда не получите один и тот же символ в списке дважды. Также, конечно, это не удастся для Nвыше, чем 36.
bobince
для данного варианта использования (если нет повторения в порядке) я скажу, что это все еще лучшее решение.
Anurag Uniyal
3
У одного из примеров есть повтор, поэтому я сомневаюсь, что он пытается запретить повторы.
Марк Байерс
5
Если random.sample предотвращает повторное использование символов, умножение размера набора символов делает возможным многократное повторение , но они все же менее вероятны, чем при чисто случайном выборе. Если мы выберем строку длиной 6 и выберем «X» в качестве первого символа, в примере выбора шансы получить «X» для второго символа такие же, как шансы получить «X» в качестве первый персонаж В реализации random.sample шансы получить 'X' в качестве любого последующего символа составляют всего 5/6 шансов получить его в качестве первого символа.
'11
1
Вероятность повторения определенного символа уменьшается при перемещении по сгенерированной строке. Генерация строки из 6 символов из 26 заглавных букв плюс 10 цифр, произвольный выбор каждого символа независимо, любая конкретная строка происходит с частотой 1 / (36 ^ 6). Вероятность генерации 'FU3WYE' и 'XXXXXX' одинакова. В примере реализации вероятность создания «XXXXXX» составляет (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) из-за возможности замены в random.sample. «XXXXXX» в 324 раза менее вероятно в примере реализации.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str это случайное значение, как 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

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

Савад КП
источник
2
uppercase_str[:N+1]
Yajo
@Yajo да, мы можем ограничить использование нарезки
Savad KP
2
@Yajo: нет, вы не хотите нарезать шестнадцатеричное значение. Вы удаляете энтропию по сравнению с полной последовательностью заглавных букв и цифр. Возможно base32-закодировать значение вместо этого (немного уменьшенная энтропия, с 36 ** n до 32 ** n, все еще лучше чем 16 ** n).
Мартин Питерс
19

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

Пол Вольф
источник
12

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

MSeifert
источник
10

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

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

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

Gubbi
источник
1
Это хорошо, хотя он будет использовать только «AF», а не «A-Z». Кроме того, код становится немного менее приятным при параметризации N.
Томас Але
9

Если вам нужна случайная строка, а не псевдослучайная , вы должны использовать 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))
Джон Ла Рой
источник
3
Как os.urandomне псевдослучайный? Возможно, он использует лучший алгоритм для генерации более случайных чисел, но он все еще псевдослучайный.
Tyilo
@ Тыло, я знаю разницу между /dev/randomи /dev/urandom. Проблема в том, что /dev/randomблокирует, когда энтропии недостаточно, что ограничивает ее полезность. Для однократного пэда /dev/urandom недостаточно, но я думаю, что здесь лучше, чем псевдослучайный.
Джон Ла Рой
1
Я бы сказал, что оба /dev/randomи /dev/urandomпсевдослучайны, но это может зависеть от вашего определения.
Tyilo
9

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

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))], "")
nemesisfixx
источник
4
Я не буду голосовать за это, но я думаю, что это слишком сложно для такой простой задачи. Возвращаемое выражение - монстр. Простое лучше, чем сложное.
Карл Смит
12
@CarlSmith, правда, мое решение кажется немного излишним для этой задачи, но я знал о других более простых решениях и просто хотел найти альтернативный путь к хорошему ответу. Без свободы творчество в опасности, поэтому я пошел дальше и разместил его.
nemesisfixx 29.12.12
7

Этот метод немного быстрее и немного раздражает, чем метод 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 строк символов рандбиты проигрывают;)

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

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

обкрадывать
источник
5

Я бы сделал это так:

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) )
Карл Смит
источник
5

Используйте функцию random.choice () от Numpy

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

Мудит джайн
источник
1
Почему я должен использовать numy random вместо python stdlib random?
Pax0r
Потому что это позволяет больше параметров в аргументах, таких как длина, переменная вероятность и выбор с заменой.
Mudit Jain
5

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

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
Асим
источник
4
>>> 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
user128956
источник
3
Но этот вариант заставит всех персонажей быть разными. И это не будет работать, если N больше len (string.ascii_uppercase + string.digits)
MarSoft
3

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

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)

если вы не хотите использовать 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)

если вы хотите сгенерировать последовательность на лету, просто установите соединение в идентичность.

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

Сами Вилар
источник
3

(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  
Иаков
источник
3

это ответ на ответ Анурага Униьяла и то, над чем я работал сам.

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()
Стопит Донк
источник
2
>>> 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'.

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

Эй Джей Уппал
источник
Хорошо, но вы могли бы использовать range(num)вместо этого, и str мог бы быть строкой str += random.choice(chars).
Сашка
2
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
Наташа
источник
2
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как он отвечает на вопрос, значительно улучшит его долгосрочную ценность. Пожалуйста, отредактируйте свой ответ, чтобы добавить пояснения.
Тоби Спейт
2
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, длина). Это простой алгоритм, который легко понять. он использует список, так что вы можете отказаться от символов, которые вам не нужны.

lawlie8
источник
1

Простой:

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
Hackaholic
источник
0

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

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]
mrvol
источник
0

Два метода:

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

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

Би Ао
источник
0

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

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

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

from passgen import passgen
string_length = int(input())
random_string = passgen(length=string_length, punctuation=False, digits=True, letters=True, case='upper')
Jarvis
источник
0

Генерация случайного 16-байтового идентификатора, содержащего буквы, цифры, '_' и '-'

os.urandom(16).translate((f'{string.ascii_letters}{string.digits}-_'*4).encode('ascii'))

socketpair
источник
0

Я смотрел на разные ответы и нашел время, чтобы прочитать документацию секретов

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

В частности, секреты следует использовать вместо генератора псевдослучайных чисел по умолчанию в модуле случайных чисел, который предназначен для моделирования и симуляции, а не для защиты или криптографии.

Более подробно рассмотрев, что он может предложить, я нашел очень удобную функцию, если вы хотите имитировать такой идентификатор, как идентификаторы Google Drive:

secrets.token_urlsafe ([nbytes = None])
Возвращает случайную URL-безопасную текстовую строку, содержащую n-байтовые случайные байты. Текст в кодировке Base64, поэтому в среднем каждый байт дает примерно 1,3 символа . Если nbytes - None или не указан, используется разумное значение по умолчанию.

Используйте его следующим образом:

import secrets
import math

def id_generator():
    id = secrets.token_urlsafe(math.floor(32 / 1.3))
    return id

print(id_generator())

Выведите идентификатор длиной 32 символа:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

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

Антонин ГАВРЕЛЬ
источник
-1
import string, random
lower = string.ascii_lowercase
upper = string.ascii_uppercase
digits = string.digits
special = '!"£$%^&*.,@#/?'

def rand_pass(l=4, u=4, d=4, s=4):
    p = []
    [p.append(random.choice(lower)) for x in range(l)]
    [p.append(random.choice(upper)) for x in range(u)]
    [p.append(random.choice(digits)) for x in range(d)]
    [p.append(random.choice(special)) for x in range(s)]
    random.shuffle(p)
    return "".join(p)

print(rand_pass())
# @5U,@A4yIZvnp%51
CONvid19
источник
-2

Я обнаружил, что это проще и чище.

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

MT Head
источник