Create a Secure Password Generator Using Python

Michelle MukaiMichelle Mukai
4 min read

Introduction

As our digital lives expand, we manage dozens of online accounts. Each one requires a unique, strong password to stay secure. But creating and remembering secure passwords can be tedious. That’s where a password generator comes in.

In this tutorial, we’ll build a secure password generator in Python from scratch. It will let users choose:

  • Password length

  • Which character types to include (uppercase, lowercase, digits, symbols)

We'll also explore:

  • How password entropy works

  • How to enforce security standards

  • How to ensure true randomness

No external libraries are needed—just the Python Standard Library.

Why Use a Password Generator?

Many people reuse simple passwords. That's risky.

Consider this:

  • A 6-character password using only lowercase letters has 308 million combinations.

  • A 12-character password using all character types has over 90 sextillion combinations.

The longer and more diverse your password, the harder it is to crack. A generator helps create passwords that:

  • Are random, avoiding predictable patterns

  • Use multiple character sets

  • Can be customized for different needs

Step-by-Step: Building the Generator

Step 1: Import Required Libraries

We start by importing modules needed for randomness and predefined character sets.

import random
import string
  • random: For secure random selection of characters.

  • string: Provides sets like ascii_letters, digits, and punctuation.

Note: For cryptographic randomness, use secrets instead of random. But for most use cases, random is sufficient and easier to understand.

Step 2: Define the Password Generator Function

Let’s define a flexible function that generates passwords based on user preferences.

def generate_password(length=12, use_upper=True, use_lower=True, use_digits=True, use_symbols=True):
    if not (use_upper or use_lower or use_digits or use_symbols):
        raise ValueError("At least one character type must be selected.")

    char_pool = ""
    if use_upper:
        char_pool += string.ascii_uppercase
    if use_lower:
        char_pool += string.ascii_lowercase
    if use_digits:
        char_pool += string.digits
    if use_symbols:
        char_pool += string.punctuation

    # Guarantee at least one character from each selected type
    password = []
    if use_upper:
        password.append(random.choice(string.ascii_uppercase))
    if use_lower:
        password.append(random.choice(string.ascii_lowercase))
    if use_digits:
        password.append(random.choice(string.digits))
    if use_symbols:
        password.append(random.choice(string.punctuation))

    # Fill the rest of the password length
    remaining_length = length - len(password)
    password += random.choices(char_pool, k=remaining_length)

    # Shuffle to prevent predictable patterns
    random.shuffle(password)

    return ''.join(password)

Key Concepts:

  • char_pool: Dynamic string that includes all allowed characters.

  • Guarantees: Ensures at least one character from each selected type is included.

  • random.choices(): Efficiently fills the rest of the password.

  • random.shuffle(): Avoids predictable placement of guaranteed characters.

Step 3: User Interaction via Console

Now we’ll prompt the user to define password rules and generate a password.

if __name__ == "__main__":
    print("=== Secure Password Generator ===")
    try:
        length = int(input("Enter password length (e.g., 12): "))
        use_upper = input("Include uppercase letters? (y/n): ").lower() == 'y'
        use_lower = input("Include lowercase letters? (y/n): ").lower() == 'y'
        use_digits = input("Include digits? (y/n): ").lower() == 'y'
        use_symbols = input("Include symbols? (y/n): ").lower() == 'y'

        password = generate_password(length, use_upper, use_lower, use_digits, use_symbols)
        print(f"\nGenerated Password: {password}")

    except ValueError as ve:
        print("Error:", ve)
    except Exception as e:
        print("Something went wrong:", e)

What's Happening:

  • The script asks the user what to include.

  • It calls the password generator function with those settings.

  • It prints the resulting password to the console.

Full Script

import random
import string

def generate_password(length=12, use_upper=True, use_lower=True, use_digits=True, use_symbols=True):
    if not (use_upper or use_lower or use_digits or use_symbols):
        raise ValueError("At least one character type must be selected.")

    char_pool = ""
    if use_upper:
        char_pool += string.ascii_uppercase
    if use_lower:
        char_pool += string.ascii_lowercase
    if use_digits:
        char_pool += string.digits
    if use_symbols:
        char_pool += string.punctuation

    # Ensure at least one character of each selected type
    password = []
    if use_upper:
        password.append(random.choice(string.ascii_uppercase))
    if use_lower:
        password.append(random.choice(string.ascii_lowercase))
    if use_digits:
        password.append(random.choice(string.digits))
    if use_symbols:
        password.append(random.choice(string.punctuation))

    # Add remaining characters
    remaining_length = length - len(password)
    password += random.choices(char_pool, k=remaining_length)

    random.shuffle(password)
    return ''.join(password)

if __name__ == "__main__":
    print("=== Secure Password Generator ===")
    try:
        length = int(input("Enter password length (e.g., 12): "))
        use_upper = input("Include uppercase letters? (y/n): ").lower() == 'y'
        use_lower = input("Include lowercase letters? (y/n): ").lower() == 'y'
        use_digits = input("Include digits? (y/n): ").lower() == 'y'
        use_symbols = input("Include symbols? (y/n): ").lower() == 'y'

        password = generate_password(length, use_upper, use_lower, use_digits, use_symbols)
        print(f"\nGenerated Password: {password}")

    except ValueError as ve:
        print("Error:", ve)
    except Exception as e:
        print("Something went wrong:", e)

Security Notes

  • Use at least 12 characters for general security.

  • Enable all character types for best results.

  • For production or highly sensitive systems, replace random with Python’s secrets module for cryptographic-grade randomness:

      import secrets
      password.append(secrets.choice(char_pool))
    

Conclusion

You've built a customizable and secure password generator in Python. It enforces good password hygiene by ensuring randomness and diversity in character sets, and it gives users control over their password structure.

This script is great for personal use, scripting needs, or as a component in larger tools like account creators, password managers, or user management systems.

0
Subscribe to my newsletter

Read articles from Michelle Mukai directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Michelle Mukai
Michelle Mukai