Password generator in python Here's a password generator I created.

### THIS PROGRAM WAS CREATED FOR LEARNING PURPOSES  ###
###   AND SHOULD NOT BE USED TO CREATE PASSWORDS!   ###

import string
from enum import Enum
from random import randint, shuffle, choice

class PasswordError(Exception):
    __module__ = Exception.__module__

# Types of characters possible
class Types(Enum):
    CAP = 'CAP' # Capital
    SMA = 'SMA' # Small
    DIG = 'DIG' # Digits
    SPE = 'SPE' # Special

# Characters for each type of possible characters
type_chars = {
    Types.CAP: string.ascii_uppercase,
    Types.SMA: string.ascii_lowercase,
    Types.DIG: string.digits,
    Types.SPE: '!()-.?[]_`~;:@#$%^&amp;*='
}

def password_generator(min_length=6, max_length=20, caps=1, small=1, digits=1, special=1):
    types = {
        Types.CAP: caps,
        Types.SMA: small,
        Types.DIG: digits,
        Types.SPE: special,
    }

    num_chars = sum(list(types.values())) # Number of mandatory characters
    min_length = max(num_chars, min_length) # In case 'num_chars' is greater

    # Number of characters required for each possible type of character
    # Is greater than maximum possible length
    if min_length &gt; max_length:
        raise PasswordError(f'No password with the given criteria')

    length = randint(min_length, max_length)

    # List that stores the "types" of possible character
    char_list = []

    # Mandatory requirements
    for typ, val in zip(types.keys(), types.values()):
        char_list.extend([typ] * val)

    # The remaining values to fill
    for rem in range(length - num_chars):
        char_list.append(choice(list(types.keys())))

    shuffle(char_list)

    password = ''

    for typ in char_list:
        password += choice(type_chars[typ])

    return password

if __name__ == '__main__':
    min_length = int(input('Minimum number of characters required: '))
    max_length = int(input('Maximum number of characters possible: '))

    print()

    caps = int(input('Number of capital letters required: '))
    small = int(input('Number of small letters required: '))
    digits = int(input('Number of digits required: '))
    special = int(input('Number of special characters required: '))

    print()

    number = int(input('Number of passwords required: '))

    print('\n' + '-' * 50 + '\n')
    print('   Here are your passwords: \n')

    for i in range(number):
        print(password_generator(min_length, max_length, caps, small, digits, special))


You can also modify the mandatory types of characters (Like 3 caps, 2 digits, etc). Also, minimum length and maximum length can be specified.

I think this code looks a bit ugly. How do I improve this?
The other answers have great hints that you should definitely follow.

However, since we are talking about passwords here, a little bit of extra security might not hurt. Especially if it's readily available in the secrets module in Python 3. secrets uses a cryptograhically strong random number generator (in contrast to the pseudo random number generator in the normal random module). There is a special warning in that regard in the docs of random. If you want to stick to random, at least use an instance of random.SystemRandom(), which is basically what secrets does. An example:

RNG = random.SystemRandom()

def password_generator(...):
    ...
    # The remaining values to fill
    type_ = list(types.keys())
    for rem in range(length - num_chars):
        char_list.append(RNG.choice(type_))
        # alternatively
        char_list.append(secrets.choice(type_))
    ...


random.choice uses what is called a pseudo-random number generator, i.e. an algorithm that generates a deterministic "randomly looking" sequence of bytes starting from a given seed. secrets.choice uses a randomness source implemented in the OS, which likely takes electrical noise and other things into consideration to generate non-deterministic random data. random.org has a comprehensive article on the differences at https://www.random.org/randomness/. And of course, there is also the obligatory Wikipedia page about Randomness.