Understand the contract
When a new exception is raised while another is being handled, Python keeps the earlier exception as context. Explicit raise NewError(...) from original expresses that the new failure was caused by the original one rather than simply happening during its handling.
Chaining lets a public API describe its own concepts without discarding the lower-level evidence. The outer message can name a configuration field while the cause explains which conversion failed.
Follow the runtime behavior
An explicit cause is available through __cause__; implicit context is available through __context__. Traceback rendering normally displays the relationship. Examples here inspect the relationship directly so output remains stable across interpreter versions.
raise ... from None suppresses the context in ordinary traceback display, but does not erase the stored __context__. Use it only when hiding implementation detail helps the intended audience; retain useful diagnostics elsewhere.
Apply it and practise
Translate errors only at a meaningful abstraction boundary. Repeated wrapping at every helper makes tracebacks longer without adding useful context. Catch the specific low-level error you intend to translate.
Exercise: parse a required port field, catch ValueError, and raise a custom ConfigurationError from it. Verify the outer message and the cause type. Compare that result with from None and explain which data is still retained.
Syntax
raise ValueError("invalid configuration") from errorExamples
Preserve an explicit cause
Use a field-specific message at a configuration boundary while preserving conversion evidence.
def parse_count(text: str) -> int:
try:
return int(text)
except ValueError as error:
raise ValueError("count must be an integer") from error
try:
parse_count("many")
except ValueError as error:
print(error)
print(type(error.__cause__).__name__)- The except block binds the conversion failure and from error records it as the explicit cause of the new exception. The outer handler can inspect both layers.
- Use a field-specific message at a configuration boundary while preserving conversion evidence.
- Do not expose raw cause messages to users if they may contain sensitive input.
- Expected output: count must be an integer ValueError
Observe implicit context
Use this inspection to understand why a traceback can show multiple exceptions even without explicit chaining.
try:
try:
int("bad")
except ValueError:
raise RuntimeError("conversion failed")
except RuntimeError as error:
print(error.__cause__ is None)
print(type(error.__context__).__name__)- Raising during the handler automatically retains the ValueError as context. Because no from clause is present, __cause__ remains None.
- Use this inspection to understand why a traceback can show multiple exceptions even without explicit chaining.
- Implicit context describes what was being handled; explicit from communicates intentional causation more clearly.
- Expected output: True ValueError
Suppress displayed context
Use a concise public error when a dictionary implementation detail would confuse callers.
try:
try:
{}["token"]
except KeyError:
raise ValueError("missing setting") from None
except ValueError as error:
print(error)
print(error.__suppress_context__)
print(type(error.__context__).__name__)- from None sets the suppression flag, while the original KeyError remains stored as context. Suppression changes normal traceback presentation rather than deleting history.
- Use a concise public error when a dictionary implementation detail would confuse callers.
- Suppression is not a security mechanism for erasing sensitive exception data.
- Expected output: missing setting True KeyError
Best practices
- raise ... from None suppresses the context in ordinary traceback display, but does not erase the stored __context__. Use it only when hiding implementation detail helps the intended audience; retain useful diagnostics elsewhere.
- Translate errors only at a meaningful abstraction boundary. Repeated wrapping at every helper makes tracebacks longer without adding useful context. Catch the specific low-level error you intend to translate.
Runtime & versions
Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Python language reference