Pembuatan string acak dengan huruf besar dan angka

1336

Saya ingin menghasilkan string berukuran N.

Itu harus terdiri dari angka-angka dan huruf besar huruf Inggris seperti:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Bagaimana saya bisa mencapai ini dengan cara pythonic ?

Hellnar
sumber
11
Ini adalah pertanyaan yang sangat populer. Saya berharap seorang ahli akan menambahkan pandangannya tentang keunikan angka acak ini untuk 3 jawaban teratas yaitu probabilitas tabrakan untuk rentang ukuran string, katakanlah dari 6 hingga 16.
pengguna
8
@buffer Sangat mudah untuk menghitung jumlah kombinasi yang memungkinkan. 10 angka + 26 huruf = 36 karakter yang memungkinkan, dengan kekuatan 6 (panjang string) sama dengan sekitar dua miliar. Aturan praktis saya untuk nilai acak adalah "jika saya menghasilkan nilai untuk setiap manusia di Bumi, berapa banyak nilai yang dapat mereka miliki masing-masing?". Dalam hal ini yang kurang dari satu nilai per orang, jadi jika ini untuk mengidentifikasi pengguna atau objek, terlalu sedikit karakter. Salah satu alternatifnya adalah dengan menambahkan huruf kecil, yang membuat Anda mencapai 62 ^ 6 = hampir 57 miliar nilai unik.
Blixt
1
Dan sementara itu mungkin tampak konyol untuk memikirkan populasi dunia, itu hanya karena Anda ingin penyangga besar untuk potensi tabrakan. Lihat masalah ulang tahun: en.wikipedia.org/wiki/Birthday_problem
Blixt
1
@ buffer, Anda akan tertarik dengan jawaban ini .
Anish Ramaswamy
Bukankah ini harus diganti namanya menjadi "generasi string acak aman secara Cryptographically ..." ?
smci

Jawaban:

2542

Jawab dalam satu baris:

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

atau bahkan lebih pendek dimulai dengan Python 3.6 menggunakan random.choices():

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

Versi yang lebih aman secara kriptografis; lihat https://stackoverflow.com/a/23728630/2213647 :

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

Secara rinci, dengan fungsi bersih untuk digunakan kembali:

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

Bagaimana cara kerjanya ?

Kami mengimpor string , modul yang berisi urutan karakter ASCII umum, dan random, modul yang berkaitan dengan generasi acak.

string.ascii_uppercase + string.digits baru saja menyatukan daftar karakter yang mewakili karakter dan huruf ASCII huruf besar:

>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_uppercase + string.digits
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

Kemudian kami menggunakan pemahaman daftar untuk membuat daftar elemen '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']

Pada contoh di atas, kami menggunakan [untuk membuat daftar, tetapi kami tidak diid_generator fungsi sehingga Python tidak membuat daftar dalam memori, tetapi menghasilkan elemen dengan cepat, satu per satu (lebih lanjut tentang ini di sini ).

Alih-alih meminta untuk membuat 'n' kali string elem , kami akan meminta Python untuk membuat 'n' kali karakter acak, diambil dari urutan karakter:

>>> random.choice("abcde")
'a'
>>> random.choice("abcde")
'd'
>>> random.choice("abcde")
'b'

Oleh karena itu random.choice(chars) for _ in range(size)benar-benar membuat urutan sizekarakter. Karakter yang dipilih secara acak dari 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']

Kemudian kita hanya bergabung dengan mereka dengan string kosong sehingga urutannya menjadi string:

>>> ''.join(['a', 'b', 'b'])
'abb'
>>> [random.choice('abcde') for _ in range(3)]
['d', 'c', 'b']
>>> ''.join(random.choice('abcde') for _ in range(3))
'dac'
Ignacio Vazquez-Abrams
sumber
7
@ jorelli: Ini bukan pemahaman daftar; itu ekspresi generator.
Ignacio Vazquez-Abrams
2
@ joreilli: Saya menambahkan catatan singkat tentang ini di jawaban, dan tautan ke jawaban yang lebih terperinci tentang iterable, daftar pemahaman, generator, dan akhirnya kata kunci hasil.
e-satis
1
Saya akan ganti rangedengan xrange.
Dr. Jan-Philip Gehrcke
1
Sangat berguna. Menariknya, Django menggunakan kode ini untuk menghasilkan kata sandi & token CSRF. Meskipun Anda harus mengganti randomdengan random.SystemRandom(): github.com/django/django/blob/…
pengguna
1
@ Chiel92, random.samplemembuat sampel tanpa penggantian, dengan kata lain, tanpa kemungkinan untuk mengulangi karakter, yang tidak ada dalam persyaratan OP. Saya tidak berpikir itu akan diinginkan untuk sebagian besar aplikasi.
ontologis
557

Pertanyaan Stack Overflow ini adalah hasil Google teratas saat ini untuk "string acak Python". Jawaban teratas saat ini adalah:

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

Ini adalah metode yang sangat baik, tetapi PRNG secara acak tidak aman secara kriptografis. Saya berasumsi banyak orang yang meneliti pertanyaan ini ingin menghasilkan string acak untuk enkripsi atau kata sandi. Anda dapat melakukan ini dengan aman dengan membuat perubahan kecil pada kode di atas:

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

Menggunakan random.SystemRandom()alih-alih hanya menggunakan / dev / urandom secara acak pada mesin * nix dan CryptGenRandom()di Windows. Ini adalah PRNG yang aman secara kriptografis. Menggunakan random.choicealih-alih random.SystemRandom().choicedalam aplikasi yang membutuhkan PRNG aman dapat berpotensi menghancurkan, dan mengingat popularitas pertanyaan ini, saya yakin kesalahan telah dilakukan berkali-kali.

Jika Anda menggunakan python3.6 atau lebih baru, Anda bisa menggunakan modul rahasia baru seperti yang disebutkan dalam jawaban MSeifert :

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

Dokumen modul juga membahas cara mudah untuk menghasilkan token aman dan praktik terbaik .

Randy Marsh
sumber
3
Ya, pustaka standar resmi untuk randomtelah memperingatkan ini: " Peringatan : Generator pseudo-acak dari modul ini tidak boleh digunakan untuk tujuan keamanan. Gunakan os.urandom () atau SystemRandom jika Anda memerlukan generator nomor pseudo-acak yang aman secara kriptografi. " Inilah refnya : random.SystemRandom dan os.urandom
lord63. j
4
Jawaban yang bagus Catatan kecil: Anda mengubahnya string.uppercaseyang dapat menyebabkan hasil yang tidak terduga tergantung pada set lokal. Menggunakan string.ascii_uppercase(atau string.ascii_letters + string.digitsuntuk base62 bukannya base36) lebih aman dalam kasus-kasus di mana encoding terlibat.
Blixt
catatan kecil - lebih baik digunakan xrangedaripada rangeyang terakhir menghasilkan daftar dalam memori, sementara yang pertama membuat iterator.
guyarad
2
Apakah sengatan acak akan selalu menjadi unik? saya ingin menggunakan kunci utama.
shakthydoss
3
@shakthydoss: tidak. Ini dapat mengembalikan "AAA000", yang merupakan string acak, dan "AAA000" berikutnya, yang juga merupakan string acak. Anda harus secara eksplisit menambahkan tanda centang untuk keunikan.
usr2564301
189

Cukup gunakan Python builtin uuid:

Jika UUID tidak apa-apa untuk keperluan Anda, gunakan paket uuid bawaan .

Solusi Satu Jalur:

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

Dalam Versi Kedalaman:

Contoh:

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

Jika Anda benar-benar membutuhkan format Anda (misalnya, "6U1S75"), Anda dapat melakukannya seperti ini:

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
sumber
14
+1 Untuk berpikir di balik pertanyaan. Mungkin Anda bisa menjelaskan secara singkat perbedaan antara uuid1 dan uuid4.
Thomas Ahle
1
Jika saya melakukan uuid1 tiga kali berturut-turut, saya mendapatkan: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4 8 karakter pertama berbeda dan sisanya sama). Ini bukan kasus dengan uuid4
Chase Roberts
9
uui1: Hasilkan UUID dari ID host, nomor urut, dan waktu saat ini. uuid4: Hasilkan UUID acak.
Bijan
7
Jika Anda ingin melewatkan string casting & hyphen replacing, Anda bisa memanggil my_uuid.get_hex () atau uuid.uuid4 (). Get_hex () dan itu akan mengembalikan string yang dihasilkan dari uuid yang tidak memiliki tanda hubung.
dshap
8
Apakah ide yang baik untuk memotong UUID? Tergantung pada seberapa kecilnya string_length, kemungkinan tabrakan bisa menjadi perhatian.
pengguna
44

Cara yang lebih sederhana, lebih cepat tetapi sedikit kurang acak adalah dengan menggunakan random.samplealih-alih memilih setiap huruf secara terpisah, Jika n-pengulangan diperbolehkan, perbesar basis acak Anda dengan n kali mis

import random
import string

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

Catatan: random.sample mencegah penggunaan kembali karakter, mengalikan ukuran dari set karakter memungkinkan beberapa kali pengulangan, tetapi mereka masih lebih kecil kemungkinannya daripada pilihan acak murni. Jika kita menggunakan string dengan panjang 6, dan kita memilih 'X' sebagai karakter pertama, dalam contoh pilihan, peluang mendapatkan 'X' untuk karakter kedua sama dengan peluang mendapatkan 'X' sebagai karakter pertama. karakter pertama. Dalam implementasi random.sample, peluang mendapatkan 'X' sebagai karakter berikutnya hanya 6/7 peluang untuk mendapatkannya sebagai karakter pertama

Anurag Uniyal
sumber
8
Cara ini tidak buruk, tetapi tidak secara acak memilih setiap karakter secara terpisah, karena sampleAnda tidak akan pernah mendapatkan karakter yang sama terdaftar dua kali. Juga tentu saja akan gagal Nlebih tinggi dari 36.
bobince
untuk kasus penggunaan yang diberikan (jika tidak ada pengulangan ok) saya akan mengatakan itu masih solusi terbaik.
Anurag Uniyal
3
Salah satu contoh memiliki pengulangan, jadi saya ragu dia ingin melarang pengulangan.
Mark Byers
5
Jika random.sample mencegah penggunaan kembali karakter, mengalikan ukuran dari set karakter membuat beberapa pengulangan dimungkinkan , tetapi mereka masih lebih kecil kemungkinannya maka mereka berada dalam pilihan acak murni. Jika kita menggunakan string dengan panjang 6, dan kita memilih 'X' sebagai karakter pertama, dalam contoh pilihan, peluang mendapatkan 'X' untuk karakter kedua sama dengan peluang mendapatkan 'X' sebagai karakter pertama. karakter pertama. Dalam implementasi random.sample, peluang mendapatkan 'X' sebagai karakter berikutnya hanya 5/6 peluang untuk mendapatkannya sebagai karakter pertama.
pcurry
1
Peluang mendapatkan karakter tertentu berulang menurun saat Anda bergerak melalui string yang dihasilkan. Menghasilkan string 6 karakter dari 26 huruf besar ditambah 10 digit, secara acak memilih masing-masing karakter, setiap string tertentu terjadi dengan frekuensi 1 / (36 ^ 6). Peluang menghasilkan 'FU3WYE' dan 'XXXXXX' adalah sama. Dalam implementasi sampel, peluang menghasilkan 'XXXXXX' adalah (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (3/6) * (2 / 6) * (1/6)) karena fitur non-penggantian random.sample. 'XXXXXX' adalah 324 kali lebih kecil kemungkinannya dalam implementasi sampel.
pcurry
32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str adalah nilai acak seperti 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str adalah 'CEA8B32E00934AAEA8C005A35D85A5C0'

Savad KP
sumber
2
uppercase_str[:N+1]
Yajo
@Yajo ya kita bisa membatasi menggunakan slicing
Savad KP
2
@Yajo: tidak, Anda tidak ingin mengiris nilai hex. Anda menghapus entropi dibandingkan dengan urutan huruf dan digit huruf besar. Mungkin base32-encode nilainya (entropi sedikit berkurang, dari 36 ** n menjadi 32 ** n, masih lebih baik dari 16 ** n).
Martijn Pieters
19

Cara yang lebih cepat, lebih mudah, dan lebih fleksibel untuk melakukan ini adalah dengan menggunakan strgenmodul ( pip install StringGenerator).

Hasilkan string acak 6-karakter dengan huruf besar dan angka:

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

Dapatkan daftar unik:

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

Jaminan satu karakter "spesial" dalam string:

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

Warna HTML acak:

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

dll.

Kita perlu menyadari bahwa ini:

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

mungkin tidak memiliki angka (atau huruf besar) di dalamnya.

strgenlebih cepat dalam waktu pengembang daripada solusi di atas. Solusi dari Ignacio adalah performa run-time tercepat dan merupakan jawaban yang tepat menggunakan Python Standard Library. Tetapi Anda tidak akan pernah menggunakannya dalam bentuk itu. Anda akan ingin menggunakan SystemRandom (atau fallback jika tidak tersedia), pastikan set karakter yang diperlukan diwakili, gunakan unicode (atau tidak), pastikan invokasi berturut-turut menghasilkan string yang unik, gunakan subset dari salah satu kelas karakter modul string, dll. Ini semua membutuhkan lebih banyak kode daripada jawaban yang diberikan. Berbagai upaya untuk menggeneralisasi suatu solusi semuanya memiliki keterbatasan yang dapat dipecahkan dengan kekuatan yang lebih besar dan daya ekspresif menggunakan bahasa templat sederhana.

Ada di PyPI:

pip install StringGenerator

Pengungkapan: Saya penulis modul strgen.

Paul Wolf
sumber
12

Dari Python 3.6 pada Anda harus menggunakan secretsmodul jika Anda membutuhkannya aman secara kriptografis, bukan randommodul (jika tidak, jawaban ini identik dengan salah satu dari @Ignacio Vazquez-Abrams):

from secrets import choice
import string

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

Satu catatan tambahan: pemahaman daftar lebih cepat dalam hal str.joindaripada menggunakan ekspresi generator!

MSeifert
sumber
10

Berdasarkan jawaban Stack Overflow lainnya, Cara paling ringan untuk membuat string acak dan angka heksadesimal acak , versi yang lebih baik daripada jawaban yang diterima adalah:

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

lebih cepat.

Gubbi
sumber
1
Ini bagus, meskipun hanya akan menggunakan 'AF' dan bukan 'A-Z'. Juga, kode menjadi sedikit kurang baik ketika parametrize N.
Thomas Ahle
9

Jika Anda membutuhkan string acak daripada pseudo acak , Anda harus menggunakan os.urandomsebagai sumber

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))
John La Rooy
sumber
3
Bagaimana os.urandomtidak pseudo acak? Mungkin menggunakan algoritma yang lebih baik untuk menghasilkan angka yang lebih acak, tetapi itu masih pseudo acak.
Tyilo
@ Tyilo, saya menyadari perbedaan antara /dev/randomdan /dev/urandom. Masalahnya adalah bahwa /dev/randomblok ketika tidak ada cukup entropi yang membatasi kegunaannya. Untuk satu kali pad /dev/urandom tidak cukup bagus, tapi saya pikir ini lebih baik daripada pseudo random di sini.
John La Rooy
1
Saya akan mengatakan bahwa keduanya /dev/randomdan /dev/urandompseudo acak, tetapi mungkin tergantung pada definisi Anda.
Tyilo
9

Saya pikir belum ada yang menjawab ini lol! Tapi hei, ini dia sendiri:

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
sumber
4
Saya tidak akan memilih ini, tapi saya pikir itu terlalu rumit untuk tugas yang sederhana. Ekspresi balik adalah monster. Sederhana lebih baik daripada kompleks.
Carl Smith
12
@CarlSmith, benar solusi saya tampaknya sedikit berlebihan untuk tugas itu, tetapi saya menyadari solusi sederhana lainnya, dan hanya ingin menemukan rute alternatif untuk jawaban yang baik. Tanpa kebebasan, kreativitas berada dalam bahaya, jadi saya teruskan dan mempostingnya.
nemesisfixx
7

Metode ini sedikit lebih cepat, dan sedikit lebih menjengkelkan, daripada metode random.choice () yang diposting Ignacio.

Itu mengambil keuntungan dari sifat algoritma pseudo-acak, dan bank pada bitwise dan dan bergeser menjadi lebih cepat daripada menghasilkan angka acak baru untuk setiap karakter.

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

... buat generator yang mengeluarkan angka 5 bit sekaligus 0..31 hingga tidak ada yang tersisa

... gabung () hasil generator pada nomor acak dengan bit yang tepat

Dengan Timeit, untuk string 32-karakter, waktunya adalah:

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

... tetapi untuk 64 string karakter, randbits kalah;)

Saya mungkin tidak akan pernah menggunakan pendekatan ini dalam kode produksi kecuali saya benar-benar tidak menyukai rekan kerja saya.

sunting: diperbarui sesuai dengan pertanyaan (hanya huruf besar dan digit), dan gunakan operator bitwise & dan >> alih-alih% dan //

rampok
sumber
5

Saya akan melakukannya dengan cara ini:

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

Atau hanya:

def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )
Carl Smith
sumber
5

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

Dokumentasi ada di sini http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html

Mudit Jain
sumber
1
Mengapa saya harus menggunakan numpy random daripada python stdlib random?
Pax0r
Karena memungkinkan lebih banyak opsi dalam argumen seperti panjang, probabilitas variabel dan seleksi dengan penggantian.
Mudit Jain
5

Terkadang 0 (nol) & O (huruf O) dapat membingungkan. Jadi saya gunakan

import uuid
uuid.uuid4().hex[:6].upper().replace('0','X').replace('O','Y')
Aseem
sumber
4
>>> import string 
>>> import random

Logika berikut masih menghasilkan 6 karakter sampel acak

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

Tidak perlu dikalikan 6

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

TK82HK
pengguna128956
sumber
3
Namun varian ini akan memaksa semua karakter berbeda. Dan itu tidak akan berfungsi jika N lebih besar dari len (string.ascii_uppercase + string.digits)
MarSoft
3

Bagi Anda yang menikmati python fungsional:

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

Ini menghasilkan iterator [tak terbatas] tidak terbatas, dari urutan acak yang bergabung, dengan terlebih dahulu menghasilkan urutan tak terbatas dari simbol yang dipilih secara acak dari kumpulan pemberian, kemudian memecah urutan ini menjadi bagian panjang yang kemudian bergabung, itu harus bekerja dengan urutan yang mendukung getitem , secara default itu hanya menghasilkan urutan acak huruf alfanumerik, meskipun Anda dapat dengan mudah memodifikasi untuk menghasilkan hal-hal lain:

misalnya untuk menghasilkan tupel angka acak:

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

jika Anda tidak ingin menggunakan generasi berikutnya, Anda bisa membuatnya bisa dipanggil:

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

jika Anda ingin membuat urutan dengan cepat, cukup setel join ke identitas.

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

Seperti yang disebutkan orang lain jika Anda membutuhkan keamanan lebih maka setel fungsi pilih yang sesuai:

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

pemilih default adalah choiceyang dapat memilih simbol yang sama beberapa kali untuk setiap chunk, jika bukan Anda ingin anggota yang sama dipilih paling banyak satu kali untuk setiap chunk maka, satu kemungkinan penggunaan:

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

kami gunakan samplesebagai pemilih kami, untuk melakukan pemilihan lengkap, sehingga potongan sebenarnya panjang 1, dan untuk bergabung kami hanya memanggil nextyang mengambil potongan yang dihasilkan sepenuhnya berikutnya, diberikan contoh ini tampaknya sedikit rumit dan ...

Samy Vilar
sumber
3

(1) Ini akan memberi Anda semua huruf besar dan angka:

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) Jika nanti Anda ingin memasukkan huruf kecil ke dalam kunci Anda, maka ini juga akan berfungsi:

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  
Yakub
sumber
3

ini adalah tanggapan Anurag Uniyal dan sesuatu yang sedang saya kerjakan sendiri.

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()
Stopit Donk
sumber
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'

The random.choicefungsi mengambil entri acak dalam daftar. Anda juga membuat daftar sehingga Anda dapat menambahkan karakter dalam forpernyataan. Pada str akhirnya adalah [ 't', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], tetapi str = "".join(str)membutuhkan peduli itu, meninggalkanmu 'tm2JUQ04CK'.

Semoga ini membantu!

AJ Uppal
sumber
Bagus, tetapi Anda bisa menggunakan range(num)sebagai gantinya, dan str bisa menjadi string str += random.choice(chars).
sashk
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
Natasha
sumber
2
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang alasannya dan / atau bagaimana ia menjawab pertanyaan akan secara signifikan meningkatkan nilai jangka panjangnya. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan.
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="")

Di sini panjang string dapat diubah dalam untuk loop yaitu untuk i dalam kisaran (1, panjang) Ini adalah algoritma sederhana yang mudah dimengerti. menggunakan daftar sehingga Anda dapat membuang karakter yang tidak Anda butuhkan.

lawlie8
sumber
1

Yang sederhana:

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

Saya ingin menyarankan Anda opsi selanjutnya:

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

Mode paranoic:

import uuid
import crypt
n = 10
crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1]
mrvol
sumber
0

Dua metode:

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


Benchmark:

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

Keluaran:

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

Kinerja metode pertama lebih baik.

Bi Ao
sumber
0

Saya telah memeriksa hampir semua jawaban tetapi tidak ada yang terlihat lebih mudah. Saya sarankan Anda untuk mencoba passgen perpustakaan yang umumnya digunakan untuk membuat kata sandi acak.

Anda dapat membuat string acak dari panjang, tanda baca, digit, huruf, dan case pilihan Anda.

Berikut kode untuk kasus Anda:

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

Hasilkan ID 16-byte acak yang berisi huruf besar, angka, '_' dan '-'

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

soketpair
sumber
0

Saya melihat jawaban yang berbeda dan meluangkan waktu untuk membaca dokumentasi rahasia

Modul rahasia digunakan untuk menghasilkan angka acak kriptografis yang kuat yang cocok untuk mengelola data seperti kata sandi, otentikasi akun, token keamanan, dan rahasia terkait.

Secara khusus, rahasia harus digunakan dalam preferensi ke generator nomor pseudo-acak default dalam modul acak, yang dirancang untuk pemodelan dan simulasi, bukan keamanan atau kriptografi.

Melihat lebih dalam apa yang ditawarkan, saya menemukan fungsi yang sangat berguna jika Anda ingin meniru ID seperti ID Google Drive:

secrets.token_urlsafe ([nbytes = None])
Mengembalikan string teks URL-safe acak, yang berisi nbytes byte acak. Teks ini disandikan Base64, sehingga rata-rata setiap byte menghasilkan sekitar 1,3 karakter . Jika nbytes Tidak Ada atau tidak disediakan, standar yang wajar digunakan.

Gunakan dengan cara berikut:

import secrets
import math

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

print(id_generator())

Keluarkan id panjang 32 karakter:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Saya tahu ini sedikit berbeda dari pertanyaan OP tapi saya berharap itu akan tetap bermanfaat bagi banyak orang yang mencari kasus penggunaan yang sama yang saya cari.

Antonin GAVREL
sumber
-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
sumber
-2

Saya menemukan ini lebih sederhana dan lebih bersih.

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 

Cukup ubah 64 untuk memvariasikan panjangnya, variasikan CharacterPool untuk melakukan hanya alpha alpha numeric atau numeric saja atau karakter aneh atau apa pun yang Anda inginkan.

Kepala MT
sumber