Random string generation with upper case letters and digits

前端 未结 30 3177
逝去的感伤
逝去的感伤 2020-11-22 02:51

I want to generate a string of size N.

It should be made up of numbers and uppercase English letters such as:

  • 6U1S75
  • 4Z4UKK
  • U911K4
相关标签:
30条回答
  • 2020-11-22 03:16
    >>> import string 
    >>> import random
    

    the following logic still generates 6 character random sample

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

    No need to multiply by 6

    >>> print ''.join(random.sample((string.ascii_uppercase+string.digits)*6,6))
    
    TK82HK
    
    0 讨论(0)
  • 2020-11-22 03:16
    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
    
    0 讨论(0)
  • 2020-11-22 03:18

    From Python 3.6 on you should use the secrets module if you need it to be cryptographically secure instead of the random module (otherwise this answer is identical to the one of @Ignacio Vazquez-Abrams):

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

    One additional note: a list-comprehension is faster in the case of str.join than using a generator expression!

    0 讨论(0)
  • 2020-11-22 03:18

    I was looking at the different answers and took time to read the documentation of secrets

    The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

    In particularly, secrets should be used in preference to the default pseudo-random number generator in the random module, which is designed for modelling and simulation, not security or cryptography.

    Looking more into what it has to offer I found a very handy function if you want to mimic an ID like Google Drive IDs:

    secrets.token_urlsafe([nbytes=None])
    Return a random URL-safe text string, containing nbytes random bytes. The text is Base64 encoded, so on average each byte results in approximately 1.3 characters. If nbytes is None or not supplied, a reasonable default is used.

    Use it the following way:

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

    Output a 32 characters length id:

    joXR8dYbBDAHpVs5ci6iD-oIgPhkeQFk
    

    I know this is slightly different from the OP's question but I expect that it would still be helpful to many who were looking for the same use-case that I was looking for.

    0 讨论(0)
  • 2020-11-22 03:18

    I would like to suggest you next option:

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

    Paranoic mode:

    import uuid
    import crypt
    n = 10
    crypt.crypt(str(uuid.uuid4())).replace('/', '').replace('.', '').upper()[-n:-1]
    
    0 讨论(0)
  • 2020-11-22 03:18

    Two methods :

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

    Output :

    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
    

    The performance of first method is better.

    0 讨论(0)
提交回复
热议问题