Code Review · Python
Python Code Review: Bare except and Swallowed Errors
Review Python code that catches every exception and hides failures.
Code Review Exercise
Review the following Python code. The goal is to load a JSON config file and return an empty dictionary if something goes wrong.
import json
def load_config(path):
try:
with open(path) as file:
return json.load(file)
except:
return {}What issues do you see before scrolling further?
Review Findings
Issue #1: Bare except catches too much
The bare except: catches almost everything, including exceptions the program probably should not hide. This can make real bugs disappear.
Issue #2: Errors are swallowed silently
Returning an empty dictionary makes the caller think the file was loaded successfully but happened to contain no settings. That is very different from the file being missing, invalid, or unreadable.
Issue #3: Different failures are treated the same
A missing file, invalid JSON, permission problem, and unexpected programming bug all become {}. That removes useful debugging information.
Issue #4: Missing logging or context
If the function chooses to recover from expected failures, it should usually log what happened or provide enough context for the caller to handle it.
Why This Is Dangerous
The code looks safe because it prevents the program from crashing. But in production, silently hiding errors can be worse than failing fast.
It is: “Which failures do we expect here, and how should the caller know they happened?”
This is the key code review skill: identify the bug, then explain the behavior you want instead.
Better Version: Catch Expected Exceptions
If the intended behavior is to return an empty config when the file is missing or invalid, catch those specific exceptions.
import json
from json import JSONDecodeError
def load_config(path):
try:
with open(path) as file:
return json.load(file)
except FileNotFoundError:
return {}
except JSONDecodeError:
return {}This is better because the code documents which failures are expected and intentionally handled.
Better Version: Log Before Recovering
In many real applications, silently returning {} is still not enough. Logging makes the failure visible.
import json
import logging
from json import JSONDecodeError
logger = logging.getLogger(__name__)
def load_config(path):
try:
with open(path) as file:
return json.load(file)
except FileNotFoundError:
logger.warning("Config file not found: %s", path)
return {}
except JSONDecodeError:
logger.warning("Config file contains invalid JSON: %s", path)
return {}Alternative: Let the Caller Decide
Sometimes this function should not recover at all. If config is required for the application to run correctly, letting the exception propagate may be the better design.
import json
def load_config(path):
with open(path) as file:
return json.load(file)This version is intentionally simple. The caller decides whether to recover, retry, show an error message, or stop the program.
What Interviewers Expect
A good answer should mention more than syntax. You want to show that you understand reliability and debuggability.
- Correctness: the code catches too many exceptions.
- Debuggability: errors disappear without logging.
- Design: the caller may need to know the load failed.
- Maintainability: future bugs become harder to diagnose.
Interview Follow-Ups
Is except Exception better than a bare except?
Usually yes, because it avoids catching some system-level exceptions. But it is still broad and should be used carefully. Specific exceptions are usually better.
Should every exception be logged?
Not always. But if code suppresses an error and continues, logging is often useful so failures are not invisible.
Is returning an empty dictionary always wrong?
No. It can be fine if an empty config is a valid fallback. The problem is doing it silently for every possible failure.
What is the main review comment?
Catch the specific exceptions you expect, and decide whether to log, return a fallback, or let the caller handle the failure.