Traceback Detective Phone Book
Build a terminal phone book while learning to read and handle Python errors.
Introduction
30 Second Summary
Looking up a saved name feels simple until the name is missing or the menu receives an unexpected answer. One small mistake can stop the whole program before the next choice appears.
In this project, you will build a Python terminal phone book filled with fictional contacts. You will use controlled crashes to make searches and menu input resilient.
What You'll Build
Picture running your phone book from Visual Studio Code as it lists contacts, handles a missing name, rejects invalid menu text, and returns to the menu without a traceback.
By the end of this project, you'll have:
- A working phone book that displays three fictional contacts from a dictionary.
- A traceback investigation that connects KeyError to the exact lookup that requested a missing contact.
- A resilient menu that survives unknown names and ValueError from non-numeric choices.
- Secret Mission: Add new contacts while rejecting blank details and duplicate names.
Are there any prerequisites?
You need a Mac with internet access. You also need permission to install software and Visual Studio Code already installed.
The setup step covers Python 3.15.1 and the Python extension published by Microsoft.
Before We Start
Before any hands-on work, lock in what you are building and why the first crash matters. You will create a fictional terminal phone book that uses a deliberate crash to show how a traceback identifies the failing line of Python code.
Set Up Python on Your Mac
Your phone book needs a Python interpreter to run the code inside phone_book.py. Visual Studio Code provides the editor.
In this step, you install Python 3.15.1 on your Mac. The Microsoft Python extension connects Visual Studio Code to that interpreter.
In this step, get ready to:
- Install Python 3.15.1 with its certificates.
- Install the Python extension published by Microsoft.
- Prepare a verified phone-book-errors workspace.
Install Python 3.15.1
The first version check reveals whether the required interpreter is already available. The result determines which setup path you follow.
- Press Cmd+Space on macOS to open Spotlight.
- Type Visual Studio Code into Spotlight.
- Press Return to open Visual Studio Code.
- Select View from the menu bar.
- Select Terminal to open the integrated terminal.
You will see a terminal panel at the bottom of Visual Studio Code.
- Check your current Python version by running this command:
python3 --version
What does this command do?
The --version option asks Python to print its version number. The command exits after displaying the result.
✔️ I see the required Python version
Your terminal shows Python 3.15.1. The required interpreter is already available on your Mac.
ⓧ I see an older Python version
The output confirms that Python is installed. This project uses the pinned 3.15.1 release.
- Open the Python 3.15.1 official release page.
- Select macOS installer in the files section.
A signed .pkg installer downloads to your Mac.
- Open the downloaded .pkg file from your Downloads folder.
- Select Continue until you reach the license agreement.
- Select Agree.
- Select Install.
Your Mac may request your login password. This request only approves the local installation.
- Approve the installation with your Mac login when prompted.
- Wait for the installer to finish copying Python to your Mac.
You will see confirmation that the installation completed.
ⓧ Command not found
This result confirms that the interpreter needs to be installed. The official installer adds Python 3.15.1 to your Mac.
- Open the Python 3.15.1 official release page.
- Select macOS installer in the files section.
A signed .pkg installer downloads to your Mac.
- Open the downloaded .pkg file from your Downloads folder.
- Select Continue until you reach the license agreement.
- Select Agree.
- Select Install.
Your Mac may request your login password. This request only approves the local installation.
- Approve the installation with your Mac login when prompted.
- Wait for the installer to finish copying Python to your Mac.
You will see confirmation that the installation completed.
Python setup not completing?
- Confirm that the downloaded installer uses the .pkg extension.
- Download the installer again from the official release page if the file does not open.
- Check that your Mac account has permission to install software.
Help me troubleshoot the Python installer on my Mac.
That is the main setup hurdle cleared. Your Mac now has the interpreter that runs the phone book.
Install certificates and the Python extension
Python uses certificates when it connects to secure websites. The installer provides a script that prepares those certificates for the new interpreter.
- In Finder, navigate to /Applications/Python 3.15/.
- Open Install Certificates.command.
You will see a command window while the certificate script runs.
A brief pause is normal while the script updates the certificate bundle.
- Wait for the certificate script to report completion.
You will see Successfully installed certifi. The final output includes update complete.
Certificate script not finishing?
- Confirm that you opened the script inside /Applications/Python 3.15/.
- Keep the command window open until the script reports completion.
Help me troubleshoot the Python certificate installation.
The interpreter runs Python on your Mac. The extension adds Python editing commands inside Visual Studio Code.
- Return to Visual Studio Code from earlier.
- Select the Extensions icon in the Activity Bar.
- Type Python into the Extensions view search box.
- Select Python published by Microsoft.
- Select Install on the extension page.
You will see the Python extension listed among your installed extensions.
Extension not installing?
- Confirm that your Mac still has an internet connection.
- Confirm that the extension publisher is Microsoft.
- Restart Visual Studio Code if the installation remains incomplete.
Help me troubleshoot the Microsoft Python extension.
Create the project workspace
A workspace keeps the phone book file in one named location. You will create the phone-book-errors folder on your Desktop.
- Click your Mac Desktop to make Finder active.
- Select File from the Finder menu bar.
- Select New Folder.
- Type phone-book-errors as the folder name.
- Press Return to save the folder name.
You will see the phone-book-errors folder on your Desktop.
- Switch back to Visual Studio Code.
- Select File from the menu bar.
- Select Open Folder.
- Select the phone-book-errors folder on your Desktop.
- Select Open.
- Select Yes, I trust the authors if the Workspace Trust dialog appears.
You will see phone-book-errors at the top of the Explorer view.
- Press Cmd+Shift+P on macOS or Ctrl+Shift+P on Windows to open the Command Palette.
- Enter Python: Select Interpreter into the Command Palette search field.
- Select Python 3.15.1 from the interpreter list.
Visual Studio Code now uses Python 3.15.1 for this workspace.
- Select the Explorer view in the Activity Bar.
- Select New File in the Explorer view.
- Type phone_book.py as the file name.
- Press Return to create the file.
You will see an empty phone_book.py tab open in the editor.
- Select View from the menu bar.
- Select Terminal to open the integrated terminal for this workspace.
Before you run the final check, make a quick prediction about the Python version the terminal reports.
- Confirm the installed interpreter version by running this command:
python3 --version
What does this result prove?
The command asks the available Python interpreter for its version. A matching result proves that Visual Studio Code's integrated terminal can access the installation.
You will see Python 3.15.1 in the terminal. Your empty phone_book.py file remains open above it.
Seeing the wrong Python version?
- Return to the Command Palette.
- Run Python: Select Interpreter again.
- Select Python 3.15.1 from the interpreter list.
- Select View from the menu bar.
- Select Terminal to create a fresh integrated terminal.
Help me fix a Python version mismatch in Visual Studio Code.
✔️ Awesome, I've got everything!
- Save phone_book.py.
Your empty Python file is ready for the phone book code.
ⓧ I'd like to double check the full code
At this checkpoint, phone_book.py is completely empty. The file contains zero characters.
- Delete any text from phone_book.py if your editor shows content.
- Save the empty phone_book.py file.
Why is this file empty?
This step prepares the interpreter and workspace. The phone book code begins in the next step.
Your Mac can now run Python files from the project workspace. Next, you will turn the empty file into a visible fictional phone book.
Display Your Fictional Phone Book
Your Python setup can now run files inside the phone-book-errors workspace. The empty phone_book.py file still has nothing to display.
A small list of fictional contacts gives you a working version to test. A dictionary keeps each name connected to one phone number.
In this step, get ready to:
- Store three fictional contacts in a dictionary.
- Print a heading above one contact per line.
- Run the file to confirm that every contact appears.
Store names with their numbers
Each contact uses the person's name as the key. The phone number is the matching value.
- Add the fictional contact data to the open phone_book.py file by pasting this code:
phone_book = {
"Amina Patel": "555-0142",
"Leo Martinez": "555-0187",
"Mei Chen": "555-0129",
}
What does this code do?
- The phone_book dictionary holds the entire directory in one place.
- Each unique name acts as a key.
- Each fictional phone number acts as the matching value.
- Save phone_book.py by pressing Cmd+S.
- Run Python: Run Python File in Terminal from the Command Palette in Visual Studio Code.
You'll see the terminal return to its prompt. Good start. Your three contact records now load without a traceback.
Seeing a Python problem?
- Check that every contact line ends with a comma.
- Check that every opening quote has a matching closing quote.
- Compare the braces in your file with the code block above.
Help me fix my contact dictionary.
Print and verify every contact
A for loop repeats the same printing step for every contact. The phone_book.items() method supplies each name with its matching number.
- Add the display logic below the phone_book dictionary by pasting this code:
print("\nFictional Phone Book")
for name, phone in phone_book.items():
print(f"- {name}: {phone}")
What does this code do?
- The first print() adds a blank line before the phone book heading.
- The for loop visits every key-value pair returned by phone_book.items().
- The name variable holds the current contact's name.
- The phone variable holds the matching number.
- The final print() inserts both values into one readable line.
- Save phone_book.py by pressing Cmd+S.
Before you run the file, which three names do you expect to see beneath the heading?
- Run Python: Run Python File in Terminal from the Command Palette.
You'll see Fictional Phone Book at the top of the output.
You'll see Amina Patel with 555-0142.
You'll see Leo Martinez with 555-0187.
You'll see Mei Chen with 555-0129.
There it is. Your phone book now turns dictionary data into a readable terminal list.
Missing a contact line?
- Check that the final print() line is indented beneath the for loop.
- Check that phone_book.items() includes both parentheses.
- Confirm that all three contacts remain inside the phone_book dictionary.
Help me find the missing phone book output.
✔️ Awesome, I've got everything!
Great. Your saved file now matches the working fictional phone book.
ⓧ I'd like to double check the full code
phone_book = {
"Amina Patel": "555-0142",
"Leo Martinez": "555-0187",
"Mei Chen": "555-0129",
}
print("\nFictional Phone Book")
for name, phone in phone_book.items():
print(f"- {name}: {phone}")
Your phone book now displays every saved contact. Next, you'll let someone search the list by name.
Trigger and Read a KeyError Traceback
Your fictional phone book already prints every saved contact. Now you will search for one saved number from a name typed in the terminal.
Direct dictionary subscription asks for one exact key. A missing key creates the traceback you will investigate.
In this step, get ready to:
- Replace the contact list with a typed name lookup.
- Confirm that a known contact returns the saved number.
- Trigger a missing-contact KeyError and trace it to the failed source line.
Replace the list with a search
- Locate the three display lines below the phone_book dictionary in phone_book.py.
- Select the entire display block.
- Replace the selected block by pasting this code:
name = input("Enter a name: ")
phone = phone_book[name]
print(f"{name}'s number is {phone}.")
What Does This Code Do?
- The input() function shows the prompt. It stores the returned string in name.
- The phone_book[name] expression uses that exact string as a dictionary key.
- The matching value is stored in phone.
- The final print() call displays the matching name and number.
- Save phone_book.py.
- Run the active file with Python: Run Python File in Terminal.
- Type Amina Patel at the prompt.
- Press Enter.
You will see Amina Patel's number is 555-0142. in the terminal. Good progress. Your phone book now turns an exact name into its saved number.
Does the Saved Number Stay Hidden?
- Check that you typed Amina Patel with the same spelling as the dictionary key.
- Confirm that phone = phone_book[name] appears before the final print() line.
- Save phone_book.py before running it again.
Help me debug the known contact lookup.
✔️ Awesome, I've got everything!
Your saved search code matches the working known-contact lookup.
ⓧ I'd like to double check the full code
phone_book = {
"Amina Patel": "555-0142",
"Leo Martinez": "555-0187",
"Mei Chen": "555-0129",
}
name = input("Enter a name: ")
phone = phone_book[name]
print(f"{name}'s number is {phone}.")
Trigger and read the traceback
Before you run this check, do you think direct lookup can produce a number for a name that is missing from the dictionary?
- Run phone_book.py with Python: Run Python File in Terminal.
- Type Nora Ellis at the prompt.
- Press Enter.
The terminal ends with KeyError: 'Nora Ellis'. This deliberate crash gives you a real traceback to investigate.
- Read the terminal's final line first.
- Move upward to the line showing phone = phone_book[name].
- Use the printed file path and line number to locate the same line in phone_book.py.
- Compare Nora Ellis with the three keys in phone_book.
How Does the Traceback Tell the Story?
- The final line names KeyError as the exception. It also shows 'Nora Ellis' as the missing key.
- The source context points to phone = phone_book[name] inside phone_book.py.
- The lookup fails because Python cannot find an exact Nora Ellis key in the dictionary.
You have confirmed that the terminal ends with KeyError: 'Nora Ellis'. You also traced the exception to phone = phone_book[name].
That is your first traceback investigation complete. Next, you will make this expected missing-name path recover cleanly while preserving valid searches.
Handle the Missing Contact
The traceback from the last step proved that an unknown name reaches the direct dictionary lookup. Python then stops the program with a KeyError.
An unknown name is an expected outcome for a phone book. A targeted exception handler recovers from that specific failure. Other bugs remain visible.
In this step, get ready to:
- Protect the direct lookup with a targeted KeyError handler.
- Route successful lookups through an else branch.
- Verify both lookup paths.
Catch the missing name
A try block marks the code that can produce an expected exception. Keeping only phone = phone_book[name] inside it gives the handler a narrow scope.
- In the open phone_book.py tab, locate the line containing phone = phone_book[name].
- Select that line plus the print line beneath it.
- Replace the selected lines with a targeted handler by pasting this code:
try:
phone = phone_book[name]
except KeyError:
print(f"No contact found for {name}.")
Why Catch Only KeyError?
- The try block limits protection to the direct lookup that can fail.
- The except KeyError branch handles a name that does not exist in phone_book.
- Other exception types still produce a traceback. Unexpected bugs remain visible.
- Save phone_book.py.
Before you run the file, do you expect Nora Ellis to stop the program or reach the new handler?
- Run the active file with Python: Run Python File in Terminal.
- Enter Nora Ellis at the prompt.
You'll see No contact found for Nora Ellis. No traceback follows.
That recovery path now works. An unknown name ends with a useful message.
Still Seeing the KeyError Traceback?
- Confirm that try: starts at the same indentation level as name = input("Enter a name: ").
- Confirm that phone = phone_book[name] is indented beneath try:.
- Remove any second direct lookup below the handler.
Help me fix the missing-contact handler.
Route successful lookups through else
The else branch runs when the lookup finishes without an exception. This keeps the success message outside the protected lookup.
- Locate the current handler beginning with try:.
- Select the handler through the friendly missing-contact message.
- Add the success path by replacing the selected handler with this complete version:
try:
phone = phone_book[name]
except KeyError:
print(f"No contact found for {name}.")
else:
print(f"{name}'s number is {phone}.")
How Do the Branches Work?
- A missing name sends execution to except KeyError.
- A saved name assigns its number to phone.
- The completed lookup then sends execution to else.
- Save phone_book.py.
Before you run both tests, which branch do you expect each name to follow?
- Run the active file with Python: Run Python File in Terminal.
- Enter Nora Ellis at the prompt.
You'll see No contact found for Nora Ellis. The run finishes without a traceback.
- Run the active file again with Python: Run Python File in Terminal.
- Enter Amina Patel at the prompt.
You'll see Amina Patel's number is 555-0142. That's the repair complete: both lookup paths now finish cleanly.
Missing the Saved Number?
- Confirm that else: aligns with except KeyError:.
- Confirm that the successful print line is indented beneath else:.
- Enter Amina Patel with the same capitalization shown in the dictionary.
Help me debug the successful lookup branch.
✔️ Awesome, I've got everything!
Your saved phone_book.py now handles missing names while preserving successful lookups.
ⓧ I'd like to double check the full code
phone_book = {
"Amina Patel": "555-0142",
"Leo Martinez": "555-0187",
"Mei Chen": "555-0129",
}
name = input("Enter a name: ")
try:
phone = phone_book[name]
except KeyError:
print(f"No contact found for {name}.")
else:
print(f"{name}'s number is {phone}.")
What Should the Full File Contain?
- The phone_book dictionary stores the three fictional contacts.
- The name input controls which key the lookup requests.
- The try statement routes missing and successful lookups through separate branches.
Your lookup now recovers from missing names without masking other errors. Next, you'll turn this one-shot search into a repeatable menu.
Build a Resilient Menu
Your phone book already turns an unknown name into a helpful message. The targeted KeyError handler keeps that expected lookup failure under control.
The program still stops after one search. A repeating menu uses functions to give each phone book task a reusable name.
Each menu choice starts as text from input(). The int() conversion turns that text into the number used by the menu.
In this step, get ready to:
- Organize the contact list plus search behavior into reusable functions.
- Add a repeating numbered menu for each phone book task.
- Test numeric choices plus text input to compare their outcomes.
Refactor the behavior into functions
A function groups one task under a name. The first function owns the contact list display.
- In phone_book.py, delete the existing code below the closing brace of the phone_book dictionary.
- Add the display function with a temporary test call by pasting this code below the dictionary:
def show_contacts():
print("\nFictional Phone Book")
for name, phone in phone_book.items():
print(f"- {name}: {phone}")
show_contacts()
What does this code do?
- The show_contacts() function prints the phone book title.
- The phone_book.items() loop supplies each saved name with its corresponding phone number.
- The temporary call runs the function immediately so you can confirm the refactor preserved the display.
- Save phone_book.py.
- Run the saved file with Python: Run Python File in Terminal.
You should see Fictional Phone Book followed by Amina Patel, Leo Martinez, plus Mei Chen on separate lines.
Great, show_contacts() now owns the complete list display.
Contacts missing from the list?
Check that for name, phone in phone_book.items(): ends with a colon. Confirm that the contact print() line is indented inside the loop.
Make sure the temporary show_contacts() call starts at the left edge of the file.
Help me debug the contact list function.
The search behavior also needs a reusable name. Its existing KeyError handler stays focused on the direct dictionary lookup.
- Replace the final show_contacts() call with this search function plus its temporary test call:
def find_contact():
name = input("Enter a name: ")
try:
phone = phone_book[name]
except KeyError:
print(f"No contact found for {name}.")
else:
print(f"{name}'s number is {phone}.")
find_contact()
How does the search function work?
- The find_contact() function contains the prompt plus the lookup behavior from the previous step.
- The try block contains only the dictionary subscription that can raise KeyError.
- The else branch prints the saved number after a successful lookup.
- The temporary call runs the search function for this check.
- Save phone_book.py.
- Run the saved file with Python: Run Python File in Terminal.
- Enter Amina Patel at the name prompt.
You should see Amina Patel's number is 555-0142. in the terminal.
That refactor is working. The successful lookup now runs through find_contact().
Search function not running?
Confirm that find_contact() begins at the left edge of the file. Check that every line inside the function uses four spaces of indentation.
Make sure the temporary find_contact() call appears below the function without indentation.
Help me fix my refactored search function.
Build and test the first menu
A while True loop keeps showing the numbered choices. The loop stops when the Quit branch reaches break.
- Replace the final temporary find_contact() call with this first version of main() plus its final call:
def main():
while True:
print("\n1. List contacts")
print("2. Find contact")
print("3. Quit")
choice = int(input("Choose 1, 2, or 3: "))
if choice == 1:
show_contacts()
elif choice == 2:
find_contact()
elif choice == 3:
print("Goodbye!")
break
else:
print("Please choose 1, 2, or 3.")
main()
How does the menu choose a task?
- The while True loop repeats the menu until the Quit branch stops it.
- The int() conversion stores the typed number in choice.
- Option 1 calls show_contacts().
- Option 2 calls find_contact().
- Option 3 prints the closing message before leaving the loop.
- Save phone_book.py.
- Run the saved file with Python: Run Python File in Terminal.
- Enter 1 at the first menu prompt.
- Enter 9 when the menu returns.
- Enter 3 when the menu returns again.
Option 1 displays all three contacts. Option 9 prints Please choose 1, 2, or 3..
The menu then returns before option 3 prints Goodbye!.
Menu not repeating?
Make sure every menu statement is indented inside while True.
Check that break appears only inside the option 3 branch.
Help me debug my repeating menu.
Before you run the menu again, do you think the word hello can become the integer that choice expects?
- Run the saved file again with Python: Run Python File in Terminal.
- Enter hello at the menu prompt.
The program stops with a traceback. Its final line names ValueError as the exception type.
Read upward from the final line. The source context points to the line where int() tried to convert hello into a whole number.
Why is this failure useful?
This is the intended shortfall in the first menu version. Text input causes int() to raise ValueError.
The traceback identifies the exact conversion that needs targeted recovery. That evidence guides the next edit.
Recover from invalid menu text
Non-numeric menu input is an expected failure. A targeted except ValueError branch can recover while leaving unrelated bugs visible.
- In main(), find this conversion line:
choice = int(input("Choose 1, 2, or 3: "))
Why can this line stop the menu?
The prompt returns a string. The int() conversion raises ValueError when that string does not contain a valid integer.
- Replace the conversion line with this targeted handler:
try:
choice = int(input("Choose 1, 2, or 3: "))
except ValueError:
print("Please enter a whole number.")
continue
How does the menu recover?
- The try block contains only the integer conversion that can raise ValueError.
- The matching handler prints Please enter a whole number. when conversion fails.
- The continue statement starts the next loop cycle so the menu appears again.
Before you test the finished menu, which inputs do you expect it to recover from?
- Save phone_book.py.
- Run the saved file with Python: Run Python File in Terminal.
- Enter hello at the first menu prompt.
- Enter 1 when the menu returns.
- Enter 2 at the next menu prompt.
- Enter Nora Ellis at the name prompt.
- Enter 3 when the menu returns.
What should you see?
- The word hello produces Please enter a whole number. before the menu returns.
- Option 1 displays all three fictional contacts.
- Searching for Nora Ellis produces No contact found for Nora Ellis. before the menu returns.
- Option 3 produces Goodbye! without an unhandled traceback.
You have built the full resilience loop. Your phone book now recovers from invalid menu text plus missing contacts.
Menu still stopping after text input?
Confirm that the conversion line is indented inside try. Check that except ValueError: aligns with try:.
Make sure continue is indented inside the exception handler. It sends execution back to the menu.
Help me debug my ValueError handler.
Your finished phone_book.py should now match the reference below.
✔️ Awesome, I've got everything!
Your functions plus the resilient menu are ready. Make sure phone_book.py is saved.
ⓧ I'd like to double check the full code
phone_book = {
"Amina Patel": "555-0142",
"Leo Martinez": "555-0187",
"Mei Chen": "555-0129",
}
def show_contacts():
print("\nFictional Phone Book")
for name, phone in phone_book.items():
print(f"- {name}: {phone}")
def find_contact():
name = input("Enter a name: ")
try:
phone = phone_book[name]
except KeyError:
print(f"No contact found for {name}.")
else:
print(f"{name}'s number is {phone}.")
def main():
while True:
print("\n1. List contacts")
print("2. Find contact")
print("3. Quit")
try:
choice = int(input("Choose 1, 2, or 3: "))
except ValueError:
print("Please enter a whole number.")
continue
if choice == 1:
show_contacts()
elif choice == 2:
find_contact()
elif choice == 3:
print("Goodbye!")
break
else:
print("Please choose 1, 2, or 3.")
main()
What should match?
Check the order of show_contacts(), find_contact(), plus main().
Inside the menu, the ValueError handler surrounds only the integer conversion. The KeyError handler remains inside find_contact().
Confirm that the final main() call starts at the left edge of the file.
Secret mission
Add Contacts Safely
Your phone book can recover from missing searches and invalid menu input. Extend it with contact creation that rejects blank values and duplicate names while keeping the menu active.
Clean Up Your Resources
Clean Up Your Resources
Your Python phone book runs entirely on your Mac with no ongoing cost. Choose a cleanup option below.
Resources you used:
- The phone-book-errors folder containing your phone_book.py source file.
- The local Python process running phone_book.py in Visual Studio Code's integrated terminal.
Keep everything running
No action needed. Choose this if you want to keep testing your phone book now.
- Leave the phone book process active in the integrated terminal.
- Keep the phone-book-errors folder on your Mac.
Pause - I'll come back to this later
Pausing means stopping the program while preserving your code for later.
- Return to the integrated terminal from earlier.
- Press Control+C to stop the active phone book process.
- Keep the phone-book-errors folder on your Mac.
The terminal prompt returns. Your phone book code remains available in the workspace.
Delete - I don't want to use this again
Deleting the folder is permanent. Your Python tools remain installed for future projects.
- Return to the integrated terminal from earlier.
- Press Control+C if the phone book menu is still active.
- Remove the phone-book-errors folder by running these commands:
cd ..
rm -rf phone-book-errors
What do these commands do?
- The first command moves the terminal to the folder that contains your project folder.
- The second command permanently removes the project folder with everything inside it.
- Confirm the cleanup by checking the Explorer sidebar in Visual Studio Code.
You should no longer be able to open phone_book.py from the workspace.
Folder Still Present?
- Check that the terminal was inside phone-book-errors before you moved up one folder.
- Check that the folder name uses the same lowercase letters and hyphens.
Help me safely remove my phone book folder.
Nice Work!
Nice Work!
Case closed! Your Python phone book now handles contact lookup through a repeatable terminal menu. It also adds valid contacts while recovering from expected input errors.
You've learned how to:
- Built a repeatable terminal phone book that uses a dictionary with focused functions to list or find fictional contacts.
- Investigated a deliberate KeyError by reading its traceback from the final exception line back to the failing dictionary lookup.
- Added targeted exception handling for KeyError and ValueError. Expected failures now keep the menu active.
- Extended the menu with add_contact() during the Secret Mission. Its validation rejects blank values and duplicate names before saving a contact.
Ready to quiz yourself?