Build a Password Generator with Python
Build a secure command-line password generator using Python fundamentals.
Introduction
30 Second Summary
Every account you create needs a strong, unique password. Coming up with random passwords on the spot is tedious, and reusing the same one everywhere is a security risk.
In this project, you will build your own password generator using Python. By the end, you will have a tool that creates secure random passwords from your terminal whenever you need one.
What You'll Build
A command-line Python script that generates cryptographically secure random passwords with customizable length and character options.
By the end of this project, you'll have:
- A working command-line tool that generates secure passwords of any length with optional special characters.
- Hands-on experience with Python fundamentals including variables, functions, conditionals, loops, and user input.
- Clean, well-structured code organized into reusable functions that you can customize for your own use.
- Secret Mission: Add a password strength meter that rates your generated passwords.
Are there any prerequisites?
None beyond basic computer literacy. This project assumes you have Python and a code editor (like VS Code or Cursor) already installed on your machine. No prior programming experience is required.
Set Up Your Project
Every password generator needs two things: a way to pick random characters and a pool of characters to pick from. Python's standard library gives you both out of the box.
In this step, you will create your project file, confirm Python runs on your machine, and explore the built-in modules that power your generator.
In this step, get ready to:
- Create a password_generator.py file in your code editor.
- Confirm Python runs your file from the terminal.
- Import the string and secrets modules and explore their contents.
Open your code editor and create your project file
You need a dedicated folder for your project and a Python file inside it. Your code editor handles both.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type VS Code (or Cursor, whichever you have installed) and press Enter to open it.
- Click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop in the file dialog.
- Click New Folder and name it password-generator.
- Select the password-generator folder and click Open (macOS) or Select Folder (Windows).
Your editor now shows the empty password-generator folder in the sidebar.
- Hover over the folder name in the Explorer sidebar and click the New File icon (it looks like a page with a plus sign).
- Type password_generator.py as the file name and press Enter.
The file opens in the editor and you are ready to write Python.
Why an underscore in the filename?
Python file names use underscores instead of hyphens. Hyphens break Python's import system, so the convention is snake_case for all .py files.
Verify Python is working
Before writing real logic, confirm that Python can run your file. A quick print statement proves the connection between your editor and the terminal.
- Add this line to password_generator.py:
print("Hello, password generator!")
- Save the file with Cmd+S (macOS) or Ctrl+S (Windows).
- Open the integrated terminal by pressing Ctrl+` (Windows) or Cmd+` (macOS). The backtick key is above the Tab key.
- Run your file using the command for your operating system:
macOS
python3 password_generator.py
Windows
python password_generator.py
You should see Hello, password generator! printed in the terminal.
Don't see the output?
- Make sure you saved the file before running the command.
- Check that your terminal is in the password-generator folder. If you opened the folder in your editor, the integrated terminal starts there automatically.
- On macOS, try python3 instead of python. Many macOS systems only recognize python3.
Still stuck? Help me figure out why my Python file isn't running in the terminal.
Import the string and secrets modules
Python's string module contains pre-built character sets like all letters and all digits. The secrets module generates cryptographically secure random values, which is exactly what you need for passwords.
- Select all the text in password_generator.py and delete it.
- Replace it with the following code:
import string
import secrets
# Print the character sets to see what each module provides
print(string.ascii_letters)
print(string.digits)
print(string.punctuation)
What does this code do?
- import string loads Python's built-in module of character set constants. You will use these as the pool of characters for your passwords.
- import secrets loads the module designed for generating cryptographically strong random numbers. This is the correct module for passwords and security tokens.
- The three print() lines show you exactly which characters live inside each constant so you know what your generator will pull from.
- Save password_generator.py.
- Run the file again in your terminal:
macOS
python3 password_generator.py
Windows
python password_generator.py
You should see three lines of output: all the uppercase and lowercase letters, then the digits 0123456789, then a string of punctuation symbols.
Why secrets instead of random?
Python's random module is designed for modelling and simulation. It is not safe for security or cryptography.
The secrets module exists specifically for generating passwords, tokens, and other sensitive values. The usage is identical (secrets.choice() works just like random.choice()), so there is no extra complexity.
Seeing a ModuleNotFoundError?
Both string and secrets are part of Python's standard library. If you see an import error, your Python installation may be incomplete or you may have a file in the same folder named string.py or secrets.py that shadows the built-in module.
Need help? Help me fix a ModuleNotFoundError for string or secrets in Python.
✔️ Awesome, I've got everything!
Great. Double check you have saved your file before moving on.
ⓧ I'd like to double check the full code
Here is what password_generator.py should look like at this point:
import string
import secrets
print(string.ascii_letters)
print(string.digits)
print(string.punctuation)
Your toolkit is ready. You have a working Python file, two powerful modules imported, and a clear picture of the characters your generator will use. Next up, you will combine these pieces to generate your first password.
Build the Character Sets and Generate a Basic Password
In the previous step, you explored what Python's character set constants look like when printed out. Now it's time to put them to work.
In this step, you'll combine those character sets into a single pool and use Python's secrets module to randomly pick characters from that pool. The result is a freshly generated password every time you run the script.
In this step, get ready to:
- Create a variable that combines letters, digits, and symbols into one character pool.
- Use secrets.choice() to pick random characters and form a password.
- Run the script and see a new random password printed each time.
Create the full character pool
Right now your file prints each character set separately. You need all of those characters combined into a single variable so secrets.choice() can pick from the entire collection at once.
- In password_generator.py, find the three print lines you added in Step 1:
print(string.ascii_letters)
print(string.digits)
print(string.punctuation)
- Delete all three of those lines and replace them with the following code:
# Combine all character types into one pool
characters = string.ascii_letters + string.digits + string.punctuation
# Set the password length
length = 12
# Pick a random character from the pool, repeated 'length' times, joined into one string
password = ''.join(secrets.choice(characters) for i in range(length))
print(password)
What does this code do?
- characters combines all lowercase letters, uppercase letters, digits, and punctuation into one long string. This is the pool that random characters get picked from.
- length = 12 sets how many characters the password will have. You'll make this dynamic with user input in a later step.
- secrets.choice(characters) picks one cryptographically secure random character from the pool. The for i in range(length) part repeats that pick 12 times.
- ''.join(...) glues all 12 characters together into a single string with nothing between them.
Why secrets instead of random?
Python's official documentation states that the secrets module "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."
For password generation, cryptographic security matters. The secrets module gives you randomness that is safe for real-world passwords.
Run the script to see your password
- Save password_generator.py.
- Run the script in your terminal by running this command:
python password_generator.py
You should see a random 12-character string printed in your terminal, made up of letters, numbers, and symbols.
- Run the command again. You should see a completely different password each time.
Not seeing any output?
- Make sure you saved the file before running the command.
- Check that you deleted all three old print lines and replaced them with the new code. Leftover lines can cause errors.
- Look for a NameError or SyntaxError in the terminal output. These usually mean a typo in a variable name or a missing parenthesis.
Ask for help: Why is my password_generator.py script not printing a password when I run it?
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here is what your complete password_generator.py file should look like at this point:
import string
import secrets
characters = string.ascii_letters + string.digits + string.punctuation
length = 12
password = ''.join(secrets.choice(characters) for i in range(length))
print(password)
Your script now generates a brand new secure password every time you run it. Next up, you'll make the tool interactive so users can choose their own password length and character options.
Add User Input and Validation
Your password generator works, but it always creates a 12-character password with every character type included. A real tool should let you customize the output.
In this step, you'll make the script interactive using Python's input() function. The script will ask the user how long they want their password, validate their answer, and let them choose whether to include special characters.
In this step, get ready to:
- Ask the user for their desired password length and validate it.
- Add a minimum length requirement for security.
- Add an option to include or exclude special characters.
Ask for the password length
Instead of hardcoding the password length, you'll ask the user to type a number. Python's input() function displays a message and waits for the user to respond.
- In password_generator.py, select and delete everything below import secrets.
- Your file should now only contain the two import lines.
- Below the imports, add this code to ask the user for a password length:
# Ask the user how long they want the password
length_input = input('How many characters long? (minimum 8): ')
# Check that the input is a valid number
if not length_input.isdigit():
print('Please enter a valid number.')
exit()
# Convert the text input to a number
length = int(length_input)
What does this code do?
- input() displays the prompt text and waits for the user to type something. Whatever they type comes back as a text string.
- .isdigit() checks whether the string contains only number characters. It catches letters, symbols, and even empty input.
- exit() stops the script immediately if validation fails.
- int(length_input) converts the text string into an actual number so you can use it for counting.
You won't see a change yet. The next chunk adds the minimum length check, and the one after that completes the script so you can run it.
Validate the minimum length
The script now accepts any number, even 1 or 2. Passwords shorter than 8 characters are trivially crackable, so you need to enforce a minimum.
- Add this code directly below the length = int(length_input) line:
# Reject passwords shorter than 8 characters
if length < 8:
print('Password must be at least 8 characters for security.')
exit()
What does this code do?
This conditional compares the number the user entered to 8. If it's too short, the script prints a helpful message explaining why and stops. The user can then rerun the script and enter a valid length.
You won't see a change yet. The next chunk adds the special characters option and completes the password generation.
Add the special characters option
Some websites don't allow special characters in passwords. Giving the user a choice makes your tool more flexible.
- Add this code below the if length < 8 block, leaving a blank line between them:
# Ask whether to include special characters
symbols_input = input('Include special characters? (yes/no): ').lower()
if symbols_input not in ('yes', 'no'):
print("Please enter 'yes' or 'no'.")
exit()
# Build the character pool based on user preference
characters = string.ascii_letters + string.digits
if symbols_input == 'yes':
characters += string.punctuation
# Generate and display the password
password = ''.join(secrets.choice(characters) for i in range(length))
print(f'\nYour generated password: {password}')
What does this code do?
- .lower() converts the user's answer to lowercase so that "Yes", "YES", and "yes" all work the same way.
- not in ('yes', 'no') checks if the answer is anything other than the two valid options.
- The characters variable starts with letters and digits. Special characters are only added if the user typed "yes".
- print(f'...') is an f-string. The {password} inside the curly braces gets replaced with the actual generated password.
- Save password_generator.py.
- Run your script in the terminal:
python password_generator.py
- When prompted, type a number (like 16) and press Enter.
- When asked about special characters, type yes or no and press Enter.
You should see a randomly generated password printed to the terminal that matches the length you requested.
Not seeing a password?
- If you see "Please enter a valid number", make sure you typed only digits (no spaces or letters) for the length.
- If you see "Please enter 'yes' or 'no'", type exactly yes or no with no extra spaces.
- If you see a SyntaxError, check that your quotes match. The print("Please enter 'yes' or 'no'.") line uses double quotes on the outside and single quotes inside.
Help me debug my password generator script.
- Try running the script again with invalid input to test your validation. Enter a letter like abc for the length, or a number less than 8 like 3.
You should see the appropriate error message and the script should stop without generating a password.
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
import string
import secrets
length_input = input('How many characters long? (minimum 8): ')
if not length_input.isdigit():
print('Please enter a valid number.')
exit()
length = int(length_input)
if length < 8:
print('Password must be at least 8 characters for security.')
exit()
symbols_input = input('Include special characters? (yes/no): ').lower()
if symbols_input not in ('yes', 'no'):
print("Please enter 'yes' or 'no'.")
exit()
characters = string.ascii_letters + string.digits
if symbols_input == 'yes':
characters += string.punctuation
password = ''.join(secrets.choice(characters) for i in range(length))
print(f'\nYour generated password: {password}')
Your password generator is now interactive and validates user input. Next up, you'll organize this code into clean, reusable functions.
Wrap Everything in Functions
Your password generator works, but all the logic runs top-to-bottom in one block. If you wanted to generate multiple passwords in a session, you would need to re-run the script every time.
Functions let you group related logic under a name and call it whenever needed. In this step, you will refactor your script into three functions that each handle one job, and add a loop so users can generate passwords back-to-back.
In this step, get ready to:
- Create a generate_password() function that returns a password string.
- Create a get_user_preferences() function that handles input and validation.
- Create a main() function with a loop for generating multiple passwords.
Create the generate_password function
The password generation logic is a self-contained task. Wrapping it in a function means you can call it with different settings each time without duplicating code.
- In password_generator.py, select all the code below the two import lines and delete it.
- Add the following generate_password function below your imports (leave a blank line between the imports and the function):
def generate_password(length, use_symbols):
"""Generate a secure random password."""
characters = string.ascii_letters + string.digits
if use_symbols:
characters += string.punctuation
password = ''.join(secrets.choice(characters) for i in range(length))
return password
What does this code do?
- The function takes two parameters: length (how many characters) and use_symbols (a boolean for whether to include special characters).
- It builds the character pool and picks random characters using secrets.choice(), just like before.
- Instead of printing the password directly, it returns the string so other code can decide what to do with it.
You won't see any output yet if you run the script. The next two functions will bring everything together.
Create the get_user_preferences function
The input prompts and validation logic belong in their own function. This version uses while True loops instead of exit() calls, giving the user a chance to correct mistakes rather than crashing the script.
- Below the generate_password function (leave a blank line between them), add the get_user_preferences function:
def get_user_preferences():
"""Ask the user for their password preferences."""
while True:
length_input = input("\nHow many characters long? (minimum 8): ")
if not length_input.isdigit():
print("Please enter a valid number.")
continue
length = int(length_input)
if length < 8:
print("Password must be at least 8 characters for security.")
continue
break
while True:
symbols_input = input("Include special characters? (yes/no): ").lower()
if symbols_input in ('yes', 'no'):
break
print("Please enter 'yes' or 'no'.")
use_symbols = symbols_input == 'yes'
return length, use_symbols
What does this code do?
- The first while True loop keeps asking for a length until the user provides a valid number of 8 or more. continue jumps back to the top of the loop, and break exits it.
- The second while True loop does the same for the symbols question, only accepting yes or no.
- The function returns a tuple of (length, use_symbols) so the caller gets both values at once.
Why while True loops instead of exit()?
Your earlier version called exit() on bad input, which killed the entire program. A while True loop is more user-friendly. It shows an error message and immediately re-asks the question.
This pattern is standard for command-line tools that need reliable input from users.
You still won't see output if you run the script. The next function calls everything.
Create the main function and run the script
The main() function is the entry point. It calls your other two functions, displays the result, and asks if the user wants another password.
- Below get_user_preferences (leave a blank line between them), add the main function and the entry point guard:
def main():
"""Run the password generator."""
print("=== Password Generator ===")
while True:
length, use_symbols = get_user_preferences()
password = generate_password(length, use_symbols)
print(f"\nYour generated password: {password}")
again = input("\nGenerate another password? (yes/no): ").lower()
if again != 'yes':
print("Goodbye!")
break
if __name__ == '__main__':
main()
What does this code do?
- print("=== Password Generator ===") displays a header when the program starts.
- The while True loop calls get_user_preferences() and generate_password(), then asks if the user wants another password. Typing anything other than yes breaks the loop.
- if __name__ == '__main__': ensures main() only runs when you execute the file directly. If you ever import this file into another script, the code inside won't run automatically.
- Save password_generator.py.
- Run the script by running this command:
python password_generator.py
- You should see === Password Generator === followed by the length prompt.
- Enter 12 for the length and yes for special characters. A random password appears.
- When asked to generate another, type yes to confirm the loop works, then type no to exit.
Script not running or showing errors?
- If you see IndentationError, check that all lines inside each function are indented with exactly 4 spaces. Mixing tabs and spaces causes this.
- If you see NameError: name 'generate_password' is not defined, make sure generate_password is defined above main in the file. Python reads top-to-bottom.
- If nothing happens at all, check that if __name__ == '__main__': is at the very bottom of the file with no indentation.
Why isn't my refactored password generator running?
✔️ Awesome, I've got everything!
Great. Double check you have saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the complete password_generator.py file. Make sure yours matches exactly:
import string
import secrets
def generate_password(length, use_symbols):
"""Generate a secure random password."""
characters = string.ascii_letters + string.digits
if use_symbols:
characters += string.punctuation
password = ''.join(secrets.choice(characters) for i in range(length))
return password
def get_user_preferences():
"""Ask the user for their password preferences."""
while True:
length_input = input("\nHow many characters long? (minimum 8): ")
if not length_input.isdigit():
print("Please enter a valid number.")
continue
length = int(length_input)
if length < 8:
print("Password must be at least 8 characters for security.")
continue
break
while True:
symbols_input = input("Include special characters? (yes/no): ").lower()
if symbols_input in ('yes', 'no'):
break
print("Please enter 'yes' or 'no'.")
use_symbols = symbols_input == 'yes'
return length, use_symbols
def main():
"""Run the password generator."""
print("=== Password Generator ===")
while True:
length, use_symbols = get_user_preferences()
password = generate_password(length, use_symbols)
print(f"\nYour generated password: {password}")
again = input("\nGenerate another password? (yes/no): ").lower()
if again != 'yes':
print("Goodbye!")
break
if __name__ == '__main__':
main()
Secret mission
Add a Password Strength Meter
Your password generator works great, but how strong are those passwords really? Build a strength meter that rates every generated password from Very Weak to Very Strong based on character variety and length.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your file to continue experimenting, or delete it for a clean slate.
Resources you used:
- password_generator.py file on your local machine.
Keep everything running
No action needed. Choose this if you want to keep using or modifying your password generator.
- Your password_generator.py file stays wherever you saved it.
- You can run it anytime with python password_generator.py from the same folder.
- Try adding new features like password history or clipboard copying.
Pause - I'll come back to this later
Since this is a local file with no running processes, there is nothing to pause. Your script only runs when you explicitly execute it.
- Your file stays on disk and uses negligible storage.
- Come back anytime and run it again from your terminal.
Delete - I don't want to use this again
Remove the project file entirely to start fresh.
- On macOS or Linux, delete the file by running:
rm ~/Desktop/password_generator.py
- On Windows, delete the file by running:
del ~\Desktop\password_generator.py
- If you saved the file somewhere other than your Desktop, navigate to that folder and delete password_generator.py from there instead.
Nice Work!
Nice Work!
You just built a fully functional command-line password generator in Python from scratch. Every time you run your script, you get a cryptographically secure password tailored to your exact preferences.
Here's what you learned:
- Built a working command-line tool in Python using variables, functions, conditionals, loops, and user input.
- Used the secrets module for cryptographically secure randomness and the string module for pre-built character sets.
- Structured your code into reusable functions with input validation and a continuous generation loop.
- Secret Mission: Added a password strength meter using scoring logic and conditionals.
Ready to quiz yourself?