Password Generator

Python Projects (Beginner)
Course 4 ยท Chapter 3 ยท Password Generator

๐Ÿ” Password Generator

A customizable password generator โ€” but the real lesson in this chapter isn't string handling, it's a genuinely important distinction most beginners never hear explicitly: random and secrets look similar but are not interchangeable for anything security-related.

๐ŸŽฎ What We're Building

A tool that asks how long the password should be and which character types to include (lowercase, uppercase, digits, symbols), then generates a genuinely random password matching those choices.

Step 1: Character Pools with the string Module

import string

print(string.ascii_lowercase)   # abcdefghijklmnopqrstuvwxyz
print(string.ascii_uppercase)   # ABCDEFGHIJKLMNOPQRSTUVWXYZ
print(string.digits)            # 0123456789
print(string.punctuation)       # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

The string module provides these character sets as ready-made constants โ€” no need to type them out by hand. Combining the ones you want (with +, Course 1, Chapter 5's string concatenation) builds the pool a password's characters get picked from.

Step 2: random vs secrets โ€” Choosing the Right Tool

import random
import secrets

random.choice("abc")    # fine for games, simulations, non-security randomness
secrets.choice("abc")   # the correct choice for anything security-sensitive
โš  random Is Not Cryptographically Secure

Course 1, Chapter 9 and the earlier projects in this course used random for a dice roll and a secret number โ€” perfectly fine there, since nothing security-sensitive depended on it. random's numbers are generated by a pseudo-random algorithm that is predictable if an attacker can determine its internal state โ€” completely unacceptable for passwords, tokens, or anything else where guessability matters. The secrets module exists specifically for this: it's built on a cryptographically secure random source, and secrets.choice() is the correct replacement for random.choice() anywhere security is actually at stake.

Step 3: Building the Password

pool = string.ascii_lowercase + string.ascii_uppercase + string.digits

password = "".join(secrets.choice(pool) for _ in range(12))
print(password)

A generator expression (Course 2, Chapter 5) calls secrets.choice(pool) once per character, 12 times; "".join(...) (Course 1, Chapter 5) combines the individual characters into one final string. _ is a common convention for a loop variable whose actual value is never used โ€” only the number of repetitions matters here.

Step 4: Letting the User Customize It

length = int(input("Password length: "))

use_upper = input("Include uppercase? (y/n): ").lower() == "y"
use_digits = input("Include digits? (y/n): ").lower() == "y"
use_symbols = input("Include symbols? (y/n): ").lower() == "y"

pool = string.ascii_lowercase
if use_upper:
    pool += string.ascii_uppercase
if use_digits:
    pool += string.digits
if use_symbols:
    pool += string.punctuation

Each if check (Course 1, Chapter 3) conditionally grows the character pool โ€” pool += is the same string-concatenation-as-accumulation pattern from Course 1, Chapter 4's loop-accumulator idea, just applied once per option instead of once per loop iteration.

๐Ÿ The Complete Password Generator

import string
import secrets

length = int(input("Password length: "))
use_upper = input("Include uppercase? (y/n): ").lower() == "y"
use_digits = input("Include digits? (y/n): ").lower() == "y"
use_symbols = input("Include symbols? (y/n): ").lower() == "y"

pool = string.ascii_lowercase
if use_upper:
    pool += string.ascii_uppercase
if use_digits:
    pool += string.digits
if use_symbols:
    pool += string.punctuation

password = "".join(secrets.choice(pool) for _ in range(length))
print(f"Your password: {password}")

string module

ascii_lowercase, ascii_uppercase, digits, punctuation โ€” ready-made character sets.

secrets, not random

Cryptographically secure โ€” the correct choice for anything security-sensitive.

Conditional pool building

Each if optionally adds a character set based on user choice.

Generator expression + join

Builds the final password one character at a time, joined into a string.

๐Ÿš€ Extend This Project

Try these on your own:

  • Guarantee at least one character from each selected type appears (right now, a short password could randomly end up all lowercase even with other options enabled) โ€” build one guaranteed character per selected type first, then fill the rest randomly.
  • Add input validation with try/except (Course 2, Chapter 3) around the length input.
  • Generate several passwords at once and let the user pick their favorite from a numbered list.
  • Add a simple strength estimate โ€” print "weak"/"medium"/"strong" based on length and how many character types were included.

๐ŸŽฏ What's Next

Next chapter: To-Do List CLI App โ€” functions and basic persistence to a text/JSON file.