
Table of Contents(目次)
- How to Implement Python Exception Handling in the Fortune Cookie Project
- Code Example Before Adding Python Exception Handling (Before)
- Code Example After Implementing Python Exception Handling (After)
- Basics of User Notification and Logging in Python Exception Handling
- Checklist for Verifying Python Exception Handling Works Correctly
- Summary: Practical Points for Python Exception Handling
How to Implement Python Exception Handling in the Fortune Cookie Project
In this lecture, you will learn how to incorporate exception handling into a real project (Fortune Cookie). The key point is not to write many fine-grained exceptions everywhere, but instead to place one or two concise exception-handling blocks that safely cover possible failure points.
- Add try-except to the actual programs (
fortune.pyandlanguage_manager.py) to handle expected failures safely. - Show clear, user-friendly messages when errors occur.
- Exception handling should be “limited to meaningful locations,” not applied everywhere just to catch all errors.
Common Types of Python Errors and Their Causes
When creating or executing modules and packages, the following three types of errors commonly occur:
- ImportError
- Raised when there is a problem loading a module via an import statement.
- ModuleNotFoundError
- A subclass of
ImportError, raised when a module cannot be found by an import statement.
- A subclass of
- AttributeError
- Raised when attempting to access a nonexistent attribute (variables, functions, etc.). Check that the target module correctly defines the variables and functions you are referencing.
Where to Write Exception Handling in Python (Key Points)
To make your program practically safe, you only need to focus on the following two points. In this lecture, we will place exception handling in these two areas.
- The module import section
- Prepare for cases where module files (e.g.,
message/language_jp.py) do not exist or cannot be loaded.
- Prepare for cases where module files (e.g.,
- Data retrieval/execution section (function calls, etc.)
- Prepare for cases where the module loads successfully, but its contents have unexpected formats that cause errors when accessed.
Scattering exception handling everywhere makes it harder to trace what happened. Therefore, it’s best practice to limit it to “critical boundaries” such as module loading, external I/O, and parsing user input.
Code Example Before Adding Python Exception Handling (Before)
First, let’s review the pre-modification state. Below are the fortune.py and manager/language_manager.py files used so far.
(Lines below if __name__ == '__main__': are omitted.)
# fortune.py
import random
import manager.language_manager as lang_manager
def main():
# Choose language
lang_code = input('Choose a language (jp/en): ')
# Receive the language-specific module
lang_module = lang_manager.get_language_module(lang_code)
messages = lang_module.MESSAGES
fortunes = lang_module.FORTUNES
# Open a cookie?
print(f"=== {messages['app_title']} ===")
answer = input(messages['prompt_open'])
if answer == 'y':
print(f"{messages['fortune_prefix']} {random.choice(fortunes)}")
else:
print(messages['goodbye'])
# manager/language_manager.py
def get_language_module(lang_code):
'''Return the module that matches the given language code'''
if lang_code == 'en':
from message import language_en
return language_en
elif lang_code == 'jp':
from message import language_jp
return language_jp
else:
print('Unsupported language code. Using Japanese instead.')
from message import language_jp
return language_jp
Code Example After Implementing Python Exception Handling (After)
Safe Handling of Import Errors (ImportError / ModuleNotFoundError)
- Protect the
importsection with try-except, and if it fails, display an error and exit the program.
# manager/language_manager.py
import sys
def get_language_module(lang_code):
'''Return the module that matches the given language code'''
try:
if lang_code == 'en':
from message import language_en
return language_en
elif lang_code == 'jp':
from message import language_jp
return language_jp
else:
print('Unsupported language code. Using Japanese instead.')
from message import language_jp
return language_jp
except ImportError as e:
print('ImportError: Required message module not found.')
print('Details:', e)
print('Exiting the program.')
sys.exit(1) # Exit with non-zero status (indicates abnormal exit)
Key points in the code:
- [Line 2, 21]
import sys,sys.exit(1)- The
sysmodule is used to return an exit status.sys.exit(1)indicates an error exit. - Additional note:
sys.exit()terminates Python and raises aSystemExitexception. When passing an integer, shells treat 0 as "normal exit" and non-zero integers as "abnormal exit." In all cases, Python terminates execution and raisesSystemExit.
- The
- [Lines 6–16]
try: ~- This block is wrapped in
trybecauseImportErrororModuleNotFoundErrormay occur when a module cannot be found.
- This block is wrapped in
- [Line 17]
except ImportError as e:- Since
ModuleNotFoundErroris a subclass ofImportError, catchingImportErrorhere covers both. - If
ModuleNotFoundErroroccurs, it will also be caught byImportError.
- Since
- [Line 18 and onward]
- Print user-friendly output explaining what happened, along with the technical details (
e), then exit safely.
- Print user-friendly output explaining what happened, along with the technical details (
How to Handle Runtime Errors in main()
After obtaining the module, the processing that follows (such as retrieving messages) is wrapped with a general except to “display details → exit safely.”
# fortune.py
import random
import manager.language_manager as lang_manager
def main():
try:
# Choose language
lang_code = input('Choose a language (jp/en): ')
# Receive the language-specific module
lang_module = lang_manager.get_language_module(lang_code)
messages = lang_module.MESSAGES
fortunes = lang_module.FORTUNES
# Open a cookie?
print(f"=== {messages['app_title']} ===")
answer = input(messages['prompt_open'])
if answer == 'y':
print(f"{messages['fortune_prefix']} {random.choice(fortunes)}")
else:
print(messages['goodbye'])
except KeyError as e:
# Handle missing keys in the MESSAGES dict
print('Internal error: Some message text is incorrectly configured.')
print('Missing key:', e)
except Exception as e:
# Catch unexpected errors for diagnostics
print('An unexpected error has occurred.')
print('Details:', e)
Key points in the code:
- [Line 8]
tryinsidedef main():- Wrapping the entire processing block prevents the program from stopping abruptly when unexpected errors occur.
- [Line 24]
except KeyError as e:- This individually handles cases where required keys are missing from the
MESSAGESdict.
- This individually handles cases where required keys are missing from the
- [Line 28]
except Exception as e:- This is a final fallback. Use this message to inform the user and later connect the information to logs or bug reports if needed.
Basics of User Notification and Logging in Python Exception Handling
For beginners, print() is sufficient, but in real-world development you’ll use the logging module to record errors to files or external monitoring systems. Keep the following two principles in mind:
- User-facing messages (print) should be concise: Tell the user “what happened” and “what to do next” briefly (e.g., “Error: Required module not found. Please contact an administrator.”).
- Technical information (error details) should go to logs: Stack traces and exception objects should be logged. Reference: Python: logging
Checklist for Verifying Python Exception Handling Works Correctly
After writing exception-handling code, try intentionally causing errors to ensure your handlers behave as expected.
- Test 1: Normal behavior — Run the program with all files present and confirm that the language messages display correctly (no errors should occur).
- Test 2: Behavior when modules are missing — Temporarily rename
message/language_jp.pyand run the program to check whether the error message is displayed and execution stops. - Test 3: Behavior when message keys are missing — Intentionally remove a key from the
MESSAGESdict inside a language module and check thatKeyErroris handled properly.
Summary: Practical Points for Python Exception Handling
This lecture introduced the minimum mechanisms required to ensure that “your program behaves clearly and safely for both users and operators when failures occur.”
- Exception handling should be neither too sparse nor too excessive—limit it to critical locations such as imports, external I/O, and user input parsing.
- In this lecture, we added simple exception handling to two areas: the import section and the execution section.
- In the future, consider introducing
loggingto record detailed exception traces to files.






