Tạo chuỗi ngẫu nhiên với chữ in hoa và chữ số


1336

Tôi muốn tạo một chuỗi có kích thước N.

Nó nên được tạo thành từ số và chữ in hoa như:

  • 6U1S75
  • 4Z4UKK
  • U911K4

Làm thế nào tôi có thể đạt được điều này một cách pythonic ?


11
Đây là một câu hỏi rất phổ biến. Tôi mong muốn một chuyên gia sẽ thêm vào tính duy nhất của các số ngẫu nhiên này cho 3 câu trả lời hàng đầu, tức là xác suất va chạm cho phạm vi kích thước chuỗi, nói từ 6 đến 16
người dùng

8
@buffer Thật dễ dàng để tính toán số lượng kết hợp có thể. 10 số + 26 chữ cái = 36 ký tự có thể, với sức mạnh là 6 (độ dài của chuỗi) bằng khoảng hai tỷ. Quy tắc ngón tay cái của tôi cho các giá trị ngẫu nhiên là "nếu tôi tạo ra các giá trị cho mỗi người trên Trái đất, thì họ có thể có bao nhiêu giá trị?". Trong trường hợp này sẽ có ít hơn một giá trị cho mỗi người, vì vậy nếu điều này là để xác định người dùng hoặc đối tượng, thì đó là quá ít ký tự. Một cách khác là thêm vào các chữ cái viết thường, đưa bạn đến 62 ^ 6 = gần 57 tỷ giá trị duy nhất.
Blixt

1
Và mặc dù có vẻ ngớ ngẩn khi nghĩ về dân số thế giới, đó chỉ là vì bạn muốn có một bộ đệm lớn cho các va chạm tiềm năng. Xem các bài toán ngày sinh: en.wikipedia.org/wiki/Birthday_problem
Blixt

1
@buffer, bạn sẽ quan tâm đến câu trả lời này rồi.
Anish Ramaswamy

Không nên đổi tên này thành "Tạo chuỗi ngẫu nhiên an toàn bằng mật mã ..." ?
smci

Câu trả lời:


2541

Trả lời trong một dòng:

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

hoặc thậm chí ngắn hơn bắt đầu với Python 3.6 bằng cách sử dụng random.choices():

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

Một phiên bản an toàn hơn về mật mã; xem https://stackoverflow.com/a/23728630/2213647 :

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

Trong chi tiết, với chức năng sạch để sử dụng lại:

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

Làm thế nào nó hoạt động ?

Chúng tôi nhập string, một mô-đun chứa các chuỗi ký tự ASCII phổ biến và randommô-đun liên quan đến việc tạo ngẫu nhiên.

string.ascii_uppercase + string.digits chỉ nối các danh sách các ký tự đại diện cho các ký tự và chữ số ASCII viết hoa:

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

Sau đó, chúng tôi sử dụng một sự hiểu biết danh sách để tạo một danh sách các yếu tố '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']

Trong ví dụ trên, chúng tôi sử dụng [để tạo danh sách, nhưng chúng tôi không có id_generatorchức năng này nên Python không tạo danh sách trong bộ nhớ, nhưng tạo ra các phần tử một cách nhanh chóng (từng phần một ở đây ).

Thay vì yêu cầu tạo 'n' lần chuỗi elem, chúng tôi sẽ yêu cầu Python tạo 'n' lần một ký tự ngẫu nhiên, được chọn từ một chuỗi các ký tự:

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

Do đó random.choice(chars) for _ in range(size)thực sự là tạo ra một chuỗi các sizenhân vật. Các ký tự được chọn ngẫu nhiên từ 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']

Sau đó, chúng ta chỉ cần nối chúng với một chuỗi rỗng để chuỗi trở thành một chuỗi:

>>> ''.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: Nó không phải là một sự hiểu biết danh sách; đó là một biểu thức máy phát điện.
Ignacio Vazquez-Abrams

2
@joreilli: Tôi đã thêm một ghi chú nhanh về điều này trong câu trả lời và liên kết đến câu trả lời chi tiết hơn về khả năng lặp lại, hiểu danh sách, trình tạo và cuối cùng là từ khóa suất.
e-satis

1
Tôi sẽ thay thế rangebằng xrange.
Tiến sĩ Jan-Philip Gehrcke

1
Rất hữu ích. Thật thú vị, Django đang sử dụng đoạn mã này để tạo mật khẩu & mã thông báo CSRF. Mặc dù bạn nên thay thế randombằng random.SystemRandom(): github.com/django/django/blob/ mẹo
người dùng

1
@ Chiel92, random.sampletạo các mẫu mà không cần thay thế, nói cách khác, không có khả năng lặp lại các ký tự, không nằm trong yêu cầu của OP. Tôi không nghĩ rằng đó là mong muốn cho hầu hết các ứng dụng.
bản thể học

557

Câu hỏi về Stack Overflow này là kết quả hàng đầu của Google hiện tại cho "chuỗi Python ngẫu nhiên". Câu trả lời hàng đầu hiện nay là:

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

Đây là một phương pháp tuyệt vời, nhưng PRNG một cách ngẫu nhiên không an toàn về mặt mật mã. Tôi giả sử nhiều người nghiên cứu câu hỏi này sẽ muốn tạo các chuỗi ngẫu nhiên để mã hóa hoặc mật khẩu. Bạn có thể thực hiện việc này một cách an toàn bằng cách thực hiện một thay đổi nhỏ trong đoạn mã trên:

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

Sử dụng random.SystemRandom()thay vì chỉ sử dụng ngẫu nhiên / dev / urandom trên các máy * nix và CryptGenRandom()trong Windows. Đây là những PRNG an toàn về mật mã. Sử dụng random.choicethay vì random.SystemRandom().choicetrong một ứng dụng yêu cầu PRNG an toàn có thể có khả năng tàn phá nghiêm trọng và với sự phổ biến của câu hỏi này, tôi cá rằng sai lầm đó đã được thực hiện nhiều lần.

Nếu bạn đang sử dụng python3.6 trở lên, bạn có thể sử dụng mô-đun bí mật mới như được đề cập trong câu trả lời của MSeifert :

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

Các tài liệu mô-đun cũng thảo luận về các cách thuận tiện để tạo mã thông báo an toànthực tiễn tốt nhất .


3
Có, thư viện tiêu chuẩn chính thức randomđã cảnh báo điều này: " Cảnh báo : Không nên sử dụng trình tạo giả ngẫu nhiên của mô-đun này cho mục đích bảo mật. Sử dụng os.urandom () hoặc SystemRandom nếu bạn yêu cầu trình tạo số giả ngẫu nhiên an toàn bằng mật mã. " Đây là ref: Random.SystemRandomos.urandom
lord63. j

4
Câu trả lời chính xác. Lưu ý nhỏ: Bạn đã thay đổi nó string.uppercasecó thể dẫn đến kết quả không mong muốn tùy thuộc vào bộ ngôn ngữ. Sử dụng string.ascii_uppercase(hoặc string.ascii_letters + string.digitscho cơ sở62 thay vì cơ sở36) sẽ an toàn hơn trong trường hợp liên quan đến mã hóa.
Blixt

lưu ý nhỏ - tốt hơn để sử dụng xrangethay vì rangecái sau tạo danh sách trong bộ nhớ, trong khi cái trước tạo ra một trình vòng lặp.
Guyarad

2
sting ngẫu nhiên sẽ luôn luôn là duy nhất? tôi muốn sử dụng khóa chính.
shakthydoss

3
@shakthydoss: không. Nó có thể trả về "AAA000", là một chuỗi ngẫu nhiên và "AAA000" tiếp theo, cũng là một chuỗi ngẫu nhiên. Bạn phải rõ ràng thêm một kiểm tra cho tính duy nhất.
usr2564301

189

Chỉ cần sử dụng uinid dựng sẵn của Python:

Nếu UUID ổn cho mục đích của bạn, hãy sử dụng gói uuid tích hợp.

Giải pháp một dòng:

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

Trong phiên bản sâu:

Thí dụ:

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

Nếu bạn cần chính xác định dạng của mình (ví dụ: "6U1S75"), bạn có thể làm như thế này:

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 Để suy nghĩ đằng sau câu hỏi. Có lẽ bạn có thể giải thích ngắn gọn về sự khác biệt giữa uuid1 và uuid4.
Thomas Ahle

1
Nếu tôi thực hiện uuid1 ba lần liên tiếp, tôi nhận được: d161fd16-ab0f-11e3-9314-00259073e4a8, d3535b56-ab0f-11e3, 935, sau đó là một số ít nhất là tương ứng với nhau. 8 ký tự đầu tiên khác nhau và phần còn lại là như nhau). Đây không phải là trường hợp với uuid4
Chase Roberts

9
uui1: Tạo UUID từ ID máy chủ, số thứ tự và thời gian hiện tại. uuid4: Tạo UUID ngẫu nhiên.
Bijan

7
Nếu bạn muốn bỏ qua việc thay thế chuỗi & gạch nối, bạn chỉ cần gọi my_uuid.get_hex () hoặc uuid.uuid4 (). Get_hex () và nó sẽ trả về một chuỗi được tạo từ uuid không có dấu gạch nối.
dshap

8
Nó có phải là một ý tưởng tốt để cắt bớt một UUID? Tùy thuộc vào mức độ nhỏ string_length, xác suất va chạm có thể là một mối quan tâm.
người dùng

44

Một cách đơn giản hơn, nhanh hơn nhưng ít ngẫu nhiên hơn là sử dụng random.samplethay vì chọn riêng từng chữ cái, Nếu cho phép lặp lại n, hãy phóng to cơ sở ngẫu nhiên của bạn thêm n lần, ví dụ:

import random
import string

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

Lưu ý: Random.sample ngăn chặn việc sử dụng lại ký tự, nhân kích thước của bộ ký tự tạo ra nhiều lần lặp lại, nhưng chúng vẫn ít có khả năng sau đó chúng nằm trong một lựa chọn ngẫu nhiên thuần túy. Nếu chúng ta chọn một chuỗi có độ dài 6 và chúng ta chọn 'X' làm ký tự đầu tiên, trong ví dụ lựa chọn, tỷ lệ nhận được 'X' cho ký tự thứ hai cũng giống như tỷ lệ nhận 'X' là nhân vật đầu tiên. Trong triển khai Random.sample, tỷ lệ nhận được 'X' là bất kỳ ký tự tiếp theo nào chỉ có 6/7 cơ hội nhận được nó làm ký tự đầu tiên


8
Cách này không tệ nhưng nó không hoàn toàn ngẫu nhiên như chọn riêng từng ký tự, vì với samplebạn sẽ không bao giờ có cùng một ký tự được liệt kê hai lần. Tất nhiên, nó sẽ thất bại Ncao hơn 36.
bobince

đối với trường hợp sử dụng đã cho (nếu không lặp lại là ok) tôi sẽ nói nó vẫn là giải pháp tốt nhất.
Anurag Uniyal

3
Một trong những ví dụ có sự lặp lại, vì vậy tôi nghi ngờ anh ta đang tìm cách không cho phép lặp lại.
Mark Byers

5
Nếu tái sử dụng ngăn chặn random.sample nhân vật, nhân kích thước của bộ ký tự làm nhiều lần lặp lại có thể , nhưng họ vẫn ít có khả năng thì họ đang ở trong một sự lựa chọn ngẫu nhiên thuần túy. Nếu chúng ta chọn một chuỗi có độ dài 6 và chúng ta chọn 'X' làm ký tự đầu tiên, trong ví dụ lựa chọn, tỷ lệ nhận 'X' cho ký tự thứ hai cũng giống như tỷ lệ nhận 'X' là nhân vật đầu tiên. Trong triển khai Random.sample, tỷ lệ nhận được 'X' như bất kỳ ký tự tiếp theo nào chỉ bằng 5/6 cơ hội nhận được nó làm ký tự đầu tiên.
pcurry

1
Cơ hội nhận được một ký tự cụ thể lặp đi lặp lại khi bạn di chuyển qua chuỗi được tạo. Tạo một chuỗi gồm 6 ký tự từ 26 chữ cái viết hoa cộng với 10 chữ số, chọn ngẫu nhiên từng ký tự một cách độc lập, bất kỳ chuỗi cụ thể nào xảy ra với tần suất 1 / (36 ^ 6). Cơ hội tạo ra 'FU3WYE' và 'XXXXXX' là như nhau. Trong triển khai mẫu, cơ hội tạo 'XXXXXX' là (1 / (36 ^ 6)) * ((6/6) * (5/6) * (4/6) * (3/6) * (2 / 6) * (1/6)) do tính năng không thay thế của Random.sample. 'XXXXXX' có khả năng thực hiện mẫu ít hơn 324 lần.
pcurry

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

lowercase_str là một giá trị ngẫu nhiên như 'cea8b32e00934aaea8c005a35d85a5c0'

uppercase_str = lowercase_str.upper()

uppercase_str'CEA8B32E00934AAEA8C005A35D85A5C0'


2
uppercase_str[:N+1]
Yajo

@Yajo vâng, chúng tôi có thể hạn chế sử dụng cắt lát
Savad KP

2
@Yajo: không, bạn không muốn cắt giá trị hex. Bạn loại bỏ entropy so với một chuỗi đầy đủ các chữ cái và chữ số viết hoa. Có lẽ thay vào đó, mã hóa base32 (entropy giảm nhẹ, từ 36 ** n xuống 32 ** n, vẫn tốt hơn 16 ** n).
Martijn Pieters

19

Một cách nhanh hơn, dễ dàng hơn và linh hoạt hơn để làm điều này là sử dụng strgenmô-đun ( pip install StringGenerator).

Tạo một chuỗi ngẫu nhiên gồm 6 ký tự với các chữ cái và chữ số viết hoa:

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

Nhận một danh sách duy nhất:

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

Đảm bảo một ký tự "đặc biệt" trong chuỗi:

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

Một màu HTML ngẫu nhiên:

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

Vân vân.

Chúng ta cần lưu ý rằng:

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

có thể không có chữ số (hoặc ký tự viết hoa) trong đó.

strgennhanh hơn trong thời gian dành cho nhà phát triển so với bất kỳ giải pháp nào ở trên. Giải pháp từ Ignacio là hiệu suất thời gian chạy nhanh nhất và là câu trả lời đúng khi sử dụng Thư viện chuẩn Python. Nhưng bạn sẽ hầu như không bao giờ sử dụng nó trong hình thức đó. Bạn sẽ muốn sử dụng SystemRandom (hoặc dự phòng nếu không có), đảm bảo các bộ ký tự được yêu cầu được trình bày, sử dụng unicode (hoặc không), đảm bảo các lệnh liên tiếp tạo ra một chuỗi duy nhất, sử dụng tập hợp con của một trong các lớp ký tự mô-đun chuỗi, vv Tất cả điều này đòi hỏi nhiều mã hơn trong các câu trả lời được cung cấp. Tất cả các nỗ lực khác nhau để khái quát hóa một giải pháp đều có những hạn chế mà strgen giải quyết với sức mạnh và sức mạnh biểu cảm lớn hơn bằng cách sử dụng một ngôn ngữ mẫu đơn giản.

Đó là trên PyPI:

pip install StringGenerator

Tiết lộ: Tôi là tác giả của mô-đun strgen.


12

Từ Python 3.6, bạn nên sử dụng secretsmô-đun nếu bạn cần bảo mật bằng mật mã thay vì randommô-đun (nếu không câu trả lời này giống hệt với mô-đun @Ignacio Vazquez-Abrams):

from secrets import choice
import string

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

Một lưu ý bổ sung: trong trường hợp hiểu danh sách sẽ nhanh hơn trong việc str.joinsử dụng biểu thức trình tạo!


10

Dựa trên một câu trả lời Stack Overflow khác, Cách nhẹ nhất để tạo một chuỗi ngẫu nhiên và một số thập lục phân ngẫu nhiên , một phiên bản tốt hơn câu trả lời được chấp nhận sẽ là:

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

nhanh hơn nhiều.


1
Điều này thật tuyệt, mặc dù nó sẽ chỉ sử dụng 'AF' chứ không phải 'A-Z'. Ngoài ra, mã trở nên ít tốt đẹp hơn khi parametrize N.
Thomas Ahle

9

Nếu bạn cần một chuỗi ngẫu nhiên thay vì một chuỗi ngẫu nhiên giả , bạn nên sử dụng os.urandomlàm nguồn

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
Làm thế nào os.urandomkhông giả ngẫu nhiên? Nó có thể đang sử dụng một thuật toán tốt hơn để tạo ra các số ngẫu nhiên hơn, nhưng nó vẫn là giả ngẫu nhiên.
Tyilo

@Tyilo, tôi nhận thức được sự khác biệt giữa /dev/random/dev/urandom. Vấn đề là /dev/randomcác khối khi không có đủ entropy làm hạn chế tính hữu dụng của nó. Đối với một miếng đệm một lần /dev/urandom là không đủ tốt, nhưng tôi nghĩ nó tốt hơn giả ngẫu nhiên ở đây.
John La Rooy

1
Tôi sẽ nói rằng cả hai /dev/random/dev/urandomlà giả ngẫu nhiên, nhưng nó có thể phụ thuộc vào định nghĩa của bạn.
Tyilo

9

Tôi nghĩ rằng không ai đã trả lời này lol! Nhưng này, đây là của riêng tôi đi vào nó:

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
Tôi sẽ không bỏ phiếu này, nhưng tôi nghĩ nó quá phức tạp cho một nhiệm vụ đơn giản như vậy. Biểu hiện trở lại là một con quái vật. Đơn giản là tốt hơn phức tạp.
Carl Smith

12
@CarlSmith, đúng là giải pháp của tôi có vẻ hơi quá mức cho nhiệm vụ, nhưng tôi đã nhận thức được các giải pháp đơn giản khác, và chỉ muốn tìm một lộ trình thay thế cho một câu trả lời hay. Không có tự do, sự sáng tạo đang gặp nguy hiểm, do đó tôi đã đi trước và đăng nó.
nemeisfixx

7

Phương thức này nhanh hơn một chút và khó chịu hơn một chút so với phương thức Random.choice () mà Ignacio đã đăng.

Nó lợi dụng bản chất của các thuật toán giả ngẫu nhiên, và các ngân hàng trên bitwise và thay đổi nhanh hơn so với việc tạo ra một số ngẫu nhiên mới cho mỗi ký tự.

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

... tạo một trình tạo lấy ra 5 số bit tại một thời điểm 0..31 cho đến khi không còn lại

... tham gia () kết quả của trình tạo trên một số ngẫu nhiên với các bit đúng

Với Timeit, đối với chuỗi 32 ký tự, thời gian là:

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

... nhưng đối với chuỗi 64 ký tự, randbits bị mất;)

Tôi có lẽ sẽ không bao giờ sử dụng phương pháp này trong mã sản xuất trừ khi tôi thực sự không thích đồng nghiệp của mình.

chỉnh sửa: được cập nhật cho phù hợp với câu hỏi (chỉ chữ hoa và chữ số) và sử dụng toán tử bitwise & và >> thay vì% và //


5

Tôi sẽ làm theo cách này:

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

Hoặc chỉ:

def rand_string(length, char_set=legals):

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

5

Sử dụng hàm Random.choice () của 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))

Tài liệu ở đây http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.random.choice.html


1
Tại sao tôi nên sử dụng ngẫu nhiên numpy thay vì python stdlib ngẫu nhiên?
Pax0r

Bởi vì nó cho phép nhiều tùy chọn hơn trong các đối số như độ dài, xác suất biến và lựa chọn với sự thay thế.
Mudit Jain

5

Đôi khi 0 (không) & O (chữ O) có thể gây nhầm lẫn. Vì vậy tôi sử dụng

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

4
>>> import string 
>>> import random

logic sau vẫn tạo mẫu ngẫu nhiên 6 ký tự

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

Không cần nhân với 6

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

TK82HK

3
Nhưng biến thể này sẽ buộc tất cả các nhân vật phải khác nhau. Và nó sẽ không hoạt động nếu N lớn hơn len (string.ascii_uppercase + string.digits)
MarSoft

3

Đối với những người bạn thích python chức năng:

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

Nó tạo ra một trình lặp [vô hạn] không xác định, các chuỗi ngẫu nhiên được nối, bằng cách đầu tiên tạo ra một chuỗi ký hiệu được chọn ngẫu nhiên không xác định từ nhóm đưa ra, sau đó chia chuỗi này thành các phần có độ dài được nối, nó sẽ hoạt động với bất kỳ chuỗi nào hỗ trợ getitem , theo mặc định, nó chỉ đơn giản tạo ra một chuỗi các chữ số alpha ngẫu nhiên, mặc dù bạn có thể dễ dàng sửa đổi để tạo ra những thứ khác:

ví dụ để tạo các bộ chữ số ngẫu nhiên:

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

nếu bạn không muốn sử dụng tiếp theo cho thế hệ, bạn chỉ cần làm cho nó có thể gọi được:

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

nếu bạn muốn tạo chuỗi nhanh, chỉ cần đặt tham gia vào danh tính.

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

Như những người khác đã đề cập nếu bạn cần bảo mật hơn thì hãy thiết lập chức năng chọn phù hợp:

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

bộ chọn mặc định choicecó thể chọn cùng một biểu tượng nhiều lần cho mỗi khối, nếu thay vào đó, bạn muốn cùng một thành viên được chọn nhiều nhất cho mỗi khối sau đó, một cách sử dụng có thể:

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

chúng tôi sử dụng samplelàm công cụ chọn của mình, để thực hiện lựa chọn hoàn chỉnh, vì vậy các khối thực sự có độ dài 1 và để tham gia, chúng tôi chỉ đơn giản gọi phần nextnào tìm nạp đoạn được tạo hoàn toàn tiếp theo, với ví dụ này có vẻ hơi cồng kềnh và nó ...


3

(1) Điều này sẽ cung cấp cho bạn tất cả các chữ hoa và số:

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) Nếu sau này bạn muốn bao gồm các chữ cái viết thường trong khóa của mình, thì điều này cũng sẽ hoạt động:

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

đây là một phản ứng của Anurag Uniyal và một cái gì đó mà tôi đang tự làm việc.

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'

Các random.choicechức năng chọn một mục ngẫu nhiên trong danh sách. Bạn cũng tạo một danh sách để bạn có thể nối thêm ký tự trong forcâu lệnh. Ở cuối str là ['t', 'm', '2', 'J', 'U', 'Q', '0', '4', 'C', 'K'], nhưng str = "".join(str)mất quan tâm đến điều đó, để lại cho bạn với 'tm2JUQ04CK'.

Hi vọng điêu nay co ich!


Đẹp, nhưng bạn có thể đã sử dụng range(num)thay thế, và str có thể là một chuỗi 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
Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do tại sao và / hoặc cách nó trả lời câu hỏi sẽ cải thiện đáng kể giá trị lâu dài của nó. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số lời giải thích.
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="")

Ở đây độ dài của chuỗi có thể được thay đổi trong vòng lặp for, tức là cho i trong phạm vi (1, độ dài) Đây là thuật toán đơn giản, dễ hiểu. nó sử dụng danh sách để bạn có thể loại bỏ các ký tự mà bạn không cần.


1

Một cái đơn giãn:

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

Tôi muốn đề nghị bạn lựa chọn tiếp theo:

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

Chế độ hoang tưởng:

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

0

Hai phương pháp:

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


Điểm chuẩn:

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

Đầu ra:

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

Hiệu suất của phương pháp đầu tiên là tốt hơn.


0

Tôi đã đi qua gần như tất cả các câu trả lời nhưng không ai trong số chúng có vẻ dễ dàng hơn. Tôi sẽ đề nghị bạn thử thư viện passgen thường được sử dụng để tạo mật khẩu ngẫu nhiên.

Bạn có thể tạo các chuỗi ngẫu nhiên theo lựa chọn về độ dài, dấu câu, chữ số, chữ cáichữ hoa .

Đây là mã cho trường hợp của bạn:

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

0

Tạo ID 16 byte ngẫu nhiên chứa các chữ cái, chữ số, '_' và '-'

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


0

Tôi đã xem xét các câu trả lời khác nhau và dành thời gian để đọc tài liệu về bí mật

Mô-đun bí mật được sử dụng để tạo các số ngẫu nhiên mạnh về mật mã phù hợp để quản lý dữ liệu như mật khẩu, xác thực tài khoản, mã thông báo bảo mật và các bí mật liên quan.

Đặc biệt, các bí mật nên được sử dụng để ưu tiên cho trình tạo số giả ngẫu nhiên mặc định trong mô-đun ngẫu nhiên, được thiết kế để mô hình hóa và mô phỏng, không phải bảo mật hoặc mật mã.

Tìm hiểu thêm về những gì nó cung cấp Tôi đã tìm thấy một chức năng rất tiện dụng nếu bạn muốn bắt chước một ID như ID Google Drive:

secret.token_urlsafe ([nbytes = Không])
Trả về một chuỗi văn bản an toàn URL ngẫu nhiên, chứa các byte ngẫu nhiên nbyte. Văn bản được mã hóa Base64, vì vậy trung bình mỗi byte cho kết quả xấp xỉ 1,3 ký tự . Nếu nbyte là Không hoặc không được cung cấp, một mặc định hợp lý được sử dụng.

Sử dụng theo cách sau:

import secrets
import math

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

print(id_generator())

Xuất id có độ dài 32 ký tự:

joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk

Tôi biết điều này hơi khác so với câu hỏi của OP nhưng tôi hy vọng rằng nó vẫn hữu ích cho nhiều người đang tìm kiếm trường hợp sử dụng tương tự mà tôi đang tìm kiếm.


-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

Tôi thấy điều này là đơn giản và sạch sẽ hơn.

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 

Chỉ cần thay đổi 64 để thay đổi độ dài, thay đổi Ký tự để thực hiện chỉ alpha số hoặc chỉ số hoặc ký tự lạ hoặc bất cứ điều gì bạn muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.