Büyük harf ve rakamlardan oluşan rastgele dize oluşturma


1335

N boyutunda bir dize oluşturmak istiyorum.

Sayılar ve büyük harflerden oluşmalıdır:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Bunu pitonik bir şekilde nasıl başarabilirim ?


11
Bu çok popüler bir soru. Bir uzmanın ilk 3 cevap için bu rastgele sayıların benzersizliğini almasını isterdim, yani dize boyutu aralığı için çarpışma olasılığı, 6'dan 16'ya kadar.
kullanıcısı

8
@buffer Olası kombinasyonların sayısını hesaplamak kolaydır. 10 rakam + 26 harf = 36 olası karakter, 6 gücüne (dize uzunluğu) yaklaşık iki milyara eşittir. Rasgele değerler için temel kuralım "Dünyadaki her insan için değer üretirsem, her birine kaç değer verebilirler?". Bu durumda, kişi başına bir değerden daha az olacaktır, bu nedenle bu, kullanıcıları veya nesneleri tanımlamaksa, çok az karakterdir. Bir alternatif, sizi 62 ​​^ 6 = neredeyse 57 milyar benzersiz değere düşüren küçük harflerle eklemek olacaktır.
Blixt

1
Ve dünya nüfusu hakkında düşünmek aptalca görünse de, bunun nedeni potansiyel çarpışmalar için devasa bir tampon istemenizdir. Doğum günü sorununa bakın: en.wikipedia.org/wiki/Birthday_problem
Blixt

1
@buffer, o zaman bu cevapla ilgilenecektiniz .
Anish Ramaswamy

Bu, "Şifrelemeyle güvenli rastgele dizgi oluşturma ..." olarak yeniden adlandırılmamalı mı?
smci

Yanıtlar:


2540

Tek satırda cevap:

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

ya da aşağıdakileri kullanarak Python 3.6 ile başlayarak daha kısa random.choices():

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

Kriptografik olarak daha güvenli bir sürüm; bkz. https://stackoverflow.com/a/23728630/2213647 :

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

Ayrıntılı olarak, daha fazla yeniden kullanım için temiz bir işlevle:

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

O nasıl çalışır ?

stringOrtak ASCII karakter dizilerini içeren randombir modül ve rastgele nesil ile ilgilenen bir modül ithal ediyoruz .

string.ascii_uppercase + string.digits büyük ASCII karakterlerini ve rakamlarını temsil eden karakterlerin listesini birleştirir:

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

Sonra 'n' öğelerinin bir listesini oluşturmak için bir liste kavrayışı kullanırız:

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

Yukarıdaki örnekte, kullandığımız [listesi oluşturmak için, ama biz değil id_generatorPython bellekte liste oluşturmaz böylece fonksiyonu, ancak anında elemanları, (bu konuda daha fazla bir tek üretir burada ).

Dizeden 'n' kez oluşturmak istemek yerine elemPython'dan bir dizi karakterden seçilen rastgele bir karakter 'n' kez oluşturmasını isteyeceğiz:

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

Bu nedenle random.choice(chars) for _ in range(size)gerçekten bir dizi sizekarakter yaratıyor . Rastgele seçilen karakterler 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']

Sonra onları boş bir dize ile birleştiririz, böylece dizi bir dize olur:

>>> ''.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: Bu bir liste kavraması değil; bu bir jeneratör ifadesidir.
Ignacio Vazquez-Abrams

2
@joreilli: Cevaba bununla ilgili kısa bir not ve yinelenebilir, liste kavrama, üreteçler ve sonuç olarak verim anahtar kelimesi hakkında daha ayrıntılı bir cevaba bağlantı ekledim.
e-satis

1
Ben değiştirecekti rangeile xrange.
Dr.Jan-Philip Gehrcke

1
Çok kullanışlı. İlginçtir ki, Django bu kod parçasını şifreler ve CSRF jetonları oluşturmak için kullanıyor. Değiştirmek gerekmesine rağmen randomsahip random.SystemRandom(): github.com/django/django/blob/...
kullanıcı

1
@ Chiel92, random.sampledeğiştirilmeden, başka bir deyişle OP'nin gereksinimlerinde olmayan karakterleri tekrar etme imkanı olmadan örnekler oluşturur. Bunun çoğu uygulama için isteneceğini düşünmüyorum.
ontolog

557

Bu Yığın Taşması sorgusu, "rastgele dize Python" için geçerli en iyi Google sonucudur. Mevcut en iyi cevap:

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

Bu mükemmel bir yöntemdir, ancak rastgele PRNG kriptografik olarak güvenli değildir. Bu soruyu araştıran birçok kişinin şifreleme veya şifreler için rastgele dizeler oluşturmak isteyeceğini düşünüyorum. Yukarıdaki kodda küçük bir değişiklik yaparak bunu güvenli bir şekilde yapabilirsiniz:

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

random.SystemRandom()* Nix makinelerinde ve CryptGenRandom()Windows'ta / dev / urandom rasgele kullanım yerine kullanmak . Bunlar kriptografik olarak güvenli PRNG'lerdir. Güvenli bir PRNG gerektiren bir uygulama random.choiceyerine kullanmak random.SystemRandom().choicepotansiyel olarak yıkıcı olabilir ve bu sorunun popülaritesi göz önüne alındığında, bu hatanın zaten birçok kez yapıldığı bahse girerim.

Python3.6 veya üstünü kullanıyorsanız, MSeifert'in cevabında belirtildiği gibi yeni sırlar modülünü kullanabilirsiniz :

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

Modül belgeleri ayrıca güvenli jetonlar ve en iyi uygulamalar oluşturmanın uygun yollarını da tartışır .


3
Evet, için resmi standart kitaplık randomşu uyarıda bulundu : " Uyarı : Bu modülün sözde rasgele üreteçleri güvenlik amacıyla kullanılmamalıdır. Şifreleme açısından güvenli bir sözde rasgele sayı üretecine ihtiyacınız varsa os.urandom () veya SystemRandom kullanın. " İşte ref: random.SystemRandom ve os.urandom
lord63. j

4
Mükemmel cevap. Küçük not: string.uppercaseYerel ayarlara bağlı olarak beklenmedik sonuçlara yol açabilecek şekilde değiştirdiniz . Kullanımı string.ascii_uppercase(ya da string.ascii_letters + string.digitsbunun yerine base36 ait base62 için) kodlayan söz konusu olduğu durumlarda daha güvenlidir.
Blixt

küçük not - ikincisi bir bellek içi liste oluştururken xrangeyerine kullanmak daha iyidir range, birincisi bir yineleyici oluşturur.
guyarad

2
rastgele acı her zaman benzersiz olacak mı? birincil anahtar kullanmak istedim.
shakthydoss

3
@shakthydoss: hayır. Rastgele bir dize olan "AAA000" ve ayrıca rastgele bir dize olan "AAA000" i döndürebilir . Benzersiz olup olmadığını açıkça kontrol etmelisiniz.
usr2564301

189

Python'un yerleşik uuid'ini kullanmanız yeterlidir:

UUID'ler amaçlarınız için uygunsa, yerleşik uuid paketini kullanın.

Tek Hat Çözümü:

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

Derinlik Versiyonunda:

Misal:

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

Tam olarak biçiminize ihtiyacınız varsa (örneğin, "6U1S75"), şu şekilde yapabilirsiniz:

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 Sorunun arkasında düşünmek için. Belki uuid1 ve uuid4 arasındaki farkı kısaca açıklayabilirsiniz.
Thomas Ahle

1
Eğer üst üste üç kez uuid1 yaparsam: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3-9314-00259073e4a8, d413be32-ab0f-11e3-9314-00259073e4a8, tamamen benzer (şüpheli gibi görünüyor) ilk 8 karakter farklıdır ve geri kalanlar aynıdır). Uuid4 ile durum böyle değil
Chase Roberts

9
uui1: Bir ana bilgisayar kimliğinden, sıra numarasından ve geçerli saatten bir UUID oluşturun. uuid4: Rastgele bir UUID oluşturun.
Bijan

7
Dizgi dökümünü ve tire işaretini atlamak istiyorsanız, my_uuid.get_hex () veya uuid.uuid4 (). Get_hex () öğesini çağırabilirsiniz ve uuid'den oluşturulan ve tireleri olmayan bir dize döndürür.
dshap

8
Bir UUID'yi kısaltmak iyi bir fikir mi? Ne kadar küçük string_lengtholduğuna bağlı olarak , çarpışma olasılığı endişe verici olabilir.
kullanıcısı

44

random.sampleHer harfi ayrı ayrı seçmek yerine daha basit, daha hızlı ama biraz daha az rastgele bir yol kullanmaktır , n-tekrarlarına izin veriliyorsa, rastgele tabanınızı n kat büyütün örn.

import random
import string

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

Not: random.sample, karakterin yeniden kullanılmasını önler, karakter kümesinin boyutunu çoğaltmak birden fazla tekrarlamayı mümkün kılar, ancak saf rastgele seçimde olma olasılıkları daha düşüktür. 6 uzunluklu bir dizeye gidersek ve ilk karakter olarak 'X'i seçersek, seçim örneğinde, ikinci karakter için' X 'elde etme olasılıkları,' X 'elde etme olasılıkları ile aynıdır. ilk karakter. Random.sample uygulamasında, sonraki herhangi bir karakter olarak 'X' elde etme olasılığı sadece 6/7, ilk karakter olarak elde etme şansıdır


8
Bu şekilde fena değil ama her karakteri ayrı ayrı seçmek kadar rastgele değil sample, aynı karakteri asla iki kez listelemeyeceksiniz. Ayrıca tabii ki Ndaha yüksek başarısız olur 36.
bobince

verilen kullanım durumunda (hiçbir tekrar tamam değilse) hala en iyi çözüm olduğunu söyleyecektir.
Anurag Uniyal

3
Örneklerden birinin bir tekrarı var, bu yüzden tekrarlara izin vermemek istediğinden şüpheliyim.
Mark Byers

5
Random.sample, karakterin yeniden kullanılmasını önlüyorsa, karakter kümesinin boyutunu çoğaltmak birden fazla tekrarlamayı mümkün kılar , ancak yine de saf rastgele seçimde olma olasılıkları daha düşüktür . 6 uzunluklu bir dizeye gidersek ve ilk karakter olarak 'X'i seçersek, seçim örneğinde, ikinci karakter için' X 'alma olasılıkları,' X 'alma olasılıkları ile aynıdır. ilk karakter. Random.sample uygulamasında, sonraki herhangi bir karakter olarak 'X' elde etme olasılığı, ilk karakter olarak alma şansı sadece 5/6'dır.
pcurry

1
Oluşturulan dizede ilerledikçe belirli bir karakteri tekrarlama şansı düşer. 26 büyük harf artı 10 basamaktan 6 karakterlik bir dize oluşturmak, her karakteri bağımsız olarak rastgele seçmek, belirli bir dize frekans 1 / (36 ^ 6) ile oluşur. 'FU3WYE' ve 'XXXXXX' oluşturma şansı aynı. Örnek uygulamada, 'XXXXXX' oluşturma şansı (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) rasgele değiştirilmeme özelliği nedeniyle. Örnek. 'XXXXXX', örnek uygulamada 324 kat daha az olasıdır.
pcurry

32
import uuid
lowercase_str = uuid.uuid4().hex  

lowercase_str gibi rastgele bir değerdir 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str dır-dir 'CEA8B32E00934AAEA8C005A35D85A5C0'


2
uppercase_str[:N+1]
Yajo

@Yajo evet dilimlemeyi kullanarak sınırlayabiliriz
Savad KP

2
@Yajo: hayır, onaltılık değeri dilimlemek istemezsiniz. Entropiyi, büyük harf ve rakamlardan oluşan tam bir diziye kıyasla kaldırırsınız. Belki de bunun yerine base32 kodlayın (hafifçe azaltılmış entropi, 36 ** n'den 32 ** n'ye, yine de 16 ** n'den daha iyi).
Martijn Pieters

19

Bunu yapmanın daha hızlı, daha kolay ve daha esnek bir yolu strgenmodülü ( pip install StringGenerator) kullanmaktır.

Büyük harf ve rakamlardan oluşan 6 karakterli rastgele bir dize oluşturun:

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

Benzersiz bir liste alın:

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

Dizede bir "özel" karakteri garanti et :

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

Rastgele bir HTML rengi:

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

vb.

Bunun farkında olmalıyız:

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

içinde bir rakam (veya büyük harf) olmayabilir.

strgengeliştirici süresinde yukarıdaki çözümlerden daha hızlıdır. Ignacio'nun çözümü en hızlı çalışma zamanı performansıdır ve Python Standart Kütüphanesi'ni kullanarak doğru cevaptır. Ama bunu asla bu biçimde kullanamazsınız. SystemRandom (veya yoksa yedek) kullanmak, gerekli karakter kümelerinin temsil edildiğinden emin olun, unicode kullanın (veya kullanmayın), ardışık çağrıların benzersiz bir dize oluşturduğundan emin olun, dize modülü karakter sınıflarından birinin alt kümesini kullanın, Bu, sağlanan cevaplardan çok daha fazla kod gerektirir. Bir çözümü genelleştirmek için yapılan çeşitli girişimlerin tümü, strgen'in basit bir şablon dili kullanarak daha büyük kısalık ve ifade gücü ile çözdüğü sınırlamalara sahiptir.

PyPI'de:

pip install StringGenerator

Açıklama: Ben strgen modülünün yazarıyım.


12

Python 3.6'dan, secretsmodül yerine şifreli olarak güvenli olması gerekiyorsarandom modülü kullanmalısınız (aksi takdirde bu cevap @Ignacio Vazquez-Abrams'ınkiyle aynıdır):

from secrets import choice
import string

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

Bir ek not: bir liste kavraması, str.joinbir jeneratör ifadesi kullanmaktan daha hızlıdır !



9

Yalancı rastgele bir dizeden ziyade rastgele bir dizeye ihtiyacınız varsa os.urandom, kaynak olarak kullanmalısınız

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.urandomYalancı rastgele nasıl değil? Daha rasgele sayılar üretmek için daha iyi bir algoritma kullanıyor olabilir, ancak yine de sözde rasgele.
Tyilo

@Tyilo, ben arasındaki farkın farkındayım /dev/randomve /dev/urandom. Sorun, /dev/randomyararlılığını sınırlayan yeterli entropi olmadığında bloke olmasıdır. Bir İçin bir kez ped /dev/urandom yeterince iyi değil, ama daha iyi burada sözde rastgele daha olduğunu düşünüyorum.
John La Rooy

1
Ben de bunu söyleyelim ki /dev/randomve /dev/urandomsözde rastgele, ama tanımına bağlı olabilir.
Tyilo

9

Kimse bu lol cevap vermişti sanıyordum! Ama hey, işte benim kendi isteğim:

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
Buna oy vermeyeceğim, ancak bence bu kadar basit bir görev için çok karmaşık. Dönüş ifadesi bir canavardır. Basit, karmaşık olmaktan iyidir.
Carl Smith

12
@CarlSmith, doğru benim çözüm görev için biraz abartılı gibi görünüyor, ama diğer daha basit çözümlerin farkındaydım ve sadece iyi bir cevaba alternatif bir yol bulmak istedim. Özgürlük olmadan, yaratıcılık tehlikede, bu yüzden devam ettim ve gönderdim.
nemesisfixx

7

Bu yöntem, Ignacio'nun gönderdiği random.choice () yönteminden biraz daha hızlı ve biraz daha sinir bozucu.

Yalancı rasgele algoritmaların doğasından yararlanır ve her karakter için yeni bir rasgele sayı üretmekten daha hızlı olmak üzere bitsel ve ve kaydırmalı bankalar.

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

... bir seferde 5 bit sayı çıkaran bir jeneratör oluşturun.

... jeneratörün sonuçlarını doğru bitlerle rastgele bir sayıya katın ()

Timeit ile 32 karakterli dizeler için zamanlama şöyleydi:

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

... ama 64 karakter dizisi için, randevular kaybeder;)

İş arkadaşlarımı gerçekten sevmediğim sürece muhtemelen bu yaklaşımı üretim kodunda kullanmam.

edit: soruya uyacak şekilde güncellendi (yalnızca büyük harf ve rakamlar) ve% ve // ​​yerine & ve >> bitsel işleçlerini kullanın


5

Bunu şu şekilde yaparım:

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

Ya da sadece:

def rand_string(length, char_set=legals):

    return ''.join( random.choice(char_set) for _ in range(length) )

5

Numpy'nin random.choice () işlevini kullan

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

Dokümantasyon burada http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html


1
Neden python stdlib random yerine numpy random kullanmalıyım?
Pax0r

Çünkü uzunluk, değişken olasılık ve değiştirmeli seçim gibi argümanlarda daha fazla seçeneğe izin verir.
Mudit Jain

5

Bazen 0 (sıfır) ve O (O harfi) kafa karıştırıcı olabilir. Bu yüzden kullanıyorum

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

4
>>> import string 
>>> import random

Aşağıdaki mantık hala 6 karakter rastgele örnek oluşturur

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

6 ile çarpmaya gerek yok

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

TK82HK

3
Ancak bu varyant tüm karakterleri farklı olmaya zorlayacaktır. Ve N
len'den büyükse

3

Fonksiyonel python'u sevenler için:

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

Öncelikle veren havuzdan rastgele seçilen sembolün belirsiz bir sekansını oluşturarak, daha sonra bu sekansı birleştirilen uzunluk parçalarına ayırarak, birleştirilmiş rastgele sekansların belirsiz bir [sonsuz] yineleyicisini üretir, getitem'i destekleyen herhangi bir sekansla çalışmalıdır. , varsayılan olarak sadece rastgele bir alfa sayısal harf dizisi oluşturur, ancak başka şeyler oluşturmak için kolayca değiştirebilirsiniz:

örneğin, rastgele sayı gruplarını oluşturmak için:

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

bir sonraki nesli kullanmak istemiyorsanız, kolayca çağrılabilir yapabilirsiniz:

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

diziyi anında oluşturmak istiyorsanız, kimliğe birleştirme ayarlayın.

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

Diğerlerinin de belirttiği gibi, daha fazla güvenliğe ihtiyacınız varsa, uygun seçme işlevini ayarlayın:

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

varsayılan seçici, choiceher bir yığın için aynı sembolü birden çok kez seçebilir, bunun yerine aynı üyenin her bir yığın için en fazla bir kez seçilmesini istiyorsanız, olası bir kullanım:

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

Kullandığımız sampleparçalar aslında uzunluğu 1 böylece, tam bir seçim yapmak ve biz sadece çağrı katılmak için, bizim seçicinin olarak nextbu örneği verilmiş sonraki tam olarak oluşturulmasına yığın, getirir biraz hantal görünüyor ve öyle ki ...


3

(1) Bu size tüm büyük harf ve sayıları verecektir:

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) Daha sonra anahtarınıza küçük harfler eklemek istiyorsanız, bu da işe yarayacaktır:

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

Bu Anurag Uniyal'un yanıtı ve kendim üzerinde çalıştığım bir şey.

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.choiceFonksiyon listesinde bir rasgele giriş alır. Ayrıca forifadeye karakteri ekleyebilmeniz için bir liste de oluşturabilirsiniz . Sonunda str ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], ancak str = "".join(str)alır bununla ilgilenirim 'tm2JUQ04CK'.

Bu yardımcı olur umarım!


Güzel, ama sen range(num)onun yerine kullanılmış olabilir ve str bir dize olabilirdi 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

2
Bu kod soruyu cevaplayabilse de, soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini önemli ölçüde artıracaktır. Lütfen biraz açıklama eklemek için cevabınızı düzenleyin .
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="")

Burada dize uzunluğu döngü için değişebilir, yani aralıktaki (1, uzunluk) i için anlaşılması kolay olan basit bir algoritmadır. listeyi kullanır, böylece ihtiyacınız olmayan karakterleri atabilirsiniz.


1

Basit bir tane:

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

Size bir sonraki seçeneği önermek istiyorum:

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

Paranoik mod:

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

0

İki yöntem:

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


Deney:

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

Çıktı :

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

İlk yöntemin performansı daha iyidir.


0

Hemen hemen tüm cevaplara rağmen gittim ama hiçbiri daha kolay görünmüyor. Genellikle rasgele şifreler oluşturmak için kullanılan passgen kütüphanesini denemenizi öneririm .

Uzunluk, noktalama işaretleri, rakamlar, harfler ve büyük / küçük harflerden oluşan rastgele dizeler oluşturabilirsiniz .

İşte davanızın kodu:

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

0

Rastgele 16 baytlık kimliğe sahip harfler, rakamlar, '_' ve '-' oluşturun

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


0

Farklı cevaplara bakıyordum ve sırların belgelerini okumak için zaman ayırdım

Sırlar modülü, parolalar, hesap kimlik doğrulaması, güvenlik belirteçleri ve ilgili sırlar gibi verileri yönetmek için uygun kriptografik olarak güçlü rasgele sayılar üretmek için kullanılır.

Özellikle, sırlar, güvenlik veya kriptografi için değil, modelleme ve simülasyon için tasarlanmış, rastgele modüldeki varsayılan sahte rasgele sayı üretecine tercih edilmelidir.

Google Drive Kimlikleri gibi bir kimliği taklit etmek istiyorsanız, sunabileceği şeylere baktığımda çok kullanışlı bir işlev buldum:

secrets.token_urlsafe ([nbytes = None])
nbyte rasgele bayt içeren rastgele URL güvenli bir metin dizesi döndürür. Metin Base64 kodludur, bu nedenle ortalama olarak her bayt yaklaşık 1,3 karakterle sonuçlanır . Nbytes Yok ise veya sağlanmazsa, makul bir varsayılan değer kullanılır.

Aşağıdaki şekilde kullanın:

import secrets
import math

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

print(id_generator())

32 karakterlik bir uzunluk kimliği girin:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Bunun OP'nin sorusundan biraz farklı olduğunu biliyorum, ancak aradığım aynı kullanım durumunu arayan birçok kişi için hala yararlı olacağını umuyorum.


-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

Bunu daha basit ve daha temiz buldum.

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 

Sadece uzunluğunu değiştirmek için 64'ü değiştirin, sadece alfa sayısal veya yalnızca sayısal veya garip karakterleri veya istediğinizi yapmak için CharacterPool'u değiştirin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.