Випадкова генерація рядків з великими літерами та цифрами


1335

Я хочу створити рядок розміром N.

Він повинен складатися з цифр і великих англійських літер, таких як:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Як я можу досягти цього пітонічним способом?


11
Це дуже популярне питання. Я хотів би, щоб експерт додав свою унікальність цих випадкових чисел для топ-3 відповідей, тобто ймовірності зіткнення для діапазону розміру рядка, скажімо, від 6 до 16.
користувач

8
@buffer Легко підрахувати кількість можливих комбінацій. 10 чисел + 26 літер = 36 можливих символів, потужність 6 (довжина рядка) дорівнює приблизно двом мільярдам. Моє правило щодо випадкових значень - "якби я створив значення для кожної людини на Землі, скільки значень міг би мати кожен з них?". У цьому випадку це буде менше одного значення на людину, тому якщо для ідентифікації користувачів або об’єктів, це занадто мало символів. Однією з альтернатив було б додати малі літери, що дає вам 62 ^ 6 = майже 57 мільярдів унікальних значень.
Бліст

1
І хоча думка про населення світу може здатися дурною, це лише тому, що ви хочете отримати величезний буфер для потенційних зіткнень. Дивіться проблему з днем ​​народження: en.wikipedia.org/wiki/Birthday_problem
Blixt

1
@buffer, тоді ця відповідь буде зацікавлена .
Аніш Рамасвамі

Чи не слід це перейменовувати у "Криптографічно безпечне генерування випадкових рядків ..." ?
smci

Відповіді:


2540

Відповідь в одному рядку:

''.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: Я додав у відповідь коротку записку про це та посилання на більш детальну відповідь про ітерабельний, розуміння списку, генератори та врешті-решт ключове слово.
e-satis

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
Так, офіційна стандартна бібліотека для 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як останній генерує список пам'яті, тоді як перший створює ітератор.
guyarad

2
чи буде випадкова жала завжди унікальною? я хотів використовувати первинний ключ.
shakthydoss

3
@shakthydoss: ні. Він може повернути "AAA000", що є випадковим рядком, і наступним "AAA000", що також є випадковим рядком. Ви повинні явно додати чек на унікальність.
usr2564301

189

Просто використовуйте вбудований uuid Python:

Якщо UUID не відповідають вашим цілям, використовуйте вбудований пакет uuid .

Однорядне рішення:

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

14
+1 Для роздуму над питанням. Можливо, ви могли б коротко пояснити різницю між uuid1 та uuid4.
Томас Ейл

1
Якщо я роблю uuid1 три рази поспіль, я отримую: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-0025907373, схоже, на перший погляд перші 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 шансів отримати його як першого символу.
pcurry

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).
Martijn Pieters

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


10

На основі іншої відповіді на переповнення стека, найлегшого способу створення випадкового рядка та випадкового шістнадцяткового числа , кращою версією, ніж прийнята відповідь, буде:

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

набагато швидше.


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є псевдо випадковим, але це може залежати від вашого визначення.
Тиїло

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

4
Я не проголосую за це, але думаю, що це занадто складно для такої простої задачі. Зворотний вираз - це чудовисько. Просте - краще, ніж складне.
Карл Сміт

12
@CarlSmith, справжнє моє рішення здається дещо непосильним для завдання, але я знав про інші простіші рішення і просто хотів знайти альтернативний шлях до гарної відповіді. Без свободи творчість загрожує небезпекою, тому я пішов і виклав її.
nemesisfixx

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, поки нічого не залишиться

... приєднати () результати генератора на випадкове число з потрібними бітами

Для Timeit для 32-символьних рядків час був такий:

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

... але для 64 символьних рядків randbits програє;)

Я, мабуть, ніколи не використовував би такий підхід у виробничому коді, якщо б справді не любив своїх колег.

редагувати: оновлено відповідно до запитання (лише великі і великі цифри), а також використовувати побітові оператори & і >> замість% та //


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
Чому я повинен використовувати numpy random замість випадкового python stdlib?
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

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)

якщо ви не хочете використовувати наступне для покоління, ви можете просто зробити його дзвінким:

>>> 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виписці. В кінці вул знаходиться [ 'т', 'т', '2', 'J', 'U', 'Q', '0', '4', 'C', 'К'], але 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
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як він відповідає на це, значно покращить його довгострокове значення. Будь ласка , змініть свій відповідь , щоб додати деякі пояснення.
Toby Speight

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

Тут можна змінити довжину рядка для циклу, тобто для i в діапазоні (1, довжина). Простий алгоритм, який легко зрозуміти. він використовує список, щоб ви могли відкинути символи, які вам не потрібні.


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

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]

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

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

Ви можете генерувати випадкові рядки на ваш вибір довжини, пунктуації, цифр, літер та .

Ось код вашої справи:

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

0

Створення випадкових 16-байтних ідентифікаторів, що містять букви, цифри, '_' та '-'

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


0

Я переглядав різні відповіді і потребував часу, щоб прочитати документацію секретів

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

Зокрема, секрети слід використовувати в перевазі генератора псевдовипадкових чисел за замовчуванням у випадковому модулі, який призначений для моделювання та моделювання, а не для захисту чи криптографії.

Розглядаючи детальніше, що вона може запропонувати, я знайшов дуже зручну функцію, якщо ви хочете імітувати ідентифікатор, такий як ідентифікатори Google Drive:

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

Використовуйте його наступним чином:

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

-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, щоб змінити довжину, варіюйте Басейн символів, щоб робити лише альфа-цифрові чисельні або лише цифрові або дивні символи чи що завгодно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.