Password Generator
๐ Password Generator
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
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.
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.