Error Handling
Error handling: try/except instead of try/catch
Section titled “Error handling: try/except instead of try/catch”Python’s error handling maps directly onto TypeScript’s try/catch/finally — with one powerful addition: an else clause that runs only when NO exception was raised. The keywords are try/except/else/finally, and you raise exceptions instead of throw.
Basic try / except
Section titled “Basic try / except”// TypeScriptfunction divide(a: number, b: number): number { if (b === 0) throw new Error("Cannot divide by zero"); return a / b;}
try { const result = divide(10, 2); console.log(`Result: ${result}`);} catch (err) { if (err instanceof Error) { console.error(`Error: ${err.message}`); }} finally { console.log("Always runs");}# Pythondef divide(a: float, b: float) -> float: if b == 0: raise ValueError("Cannot divide by zero") return a / b
try: result = divide(10, 2) print(f"Result: {result}")except ValueError as e: print(f"Error: {e}")finally: print("Always runs")Key differences:
exceptinstead ofcatch.raiseinstead ofthrow.- You catch a specific exception type directly (e.g.
except ValueError), not a generic value. - The
as esyntax binds the exception object.
Multiple exception types
Section titled “Multiple exception types”// TypeScripttry { const data = JSON.parse("{ bad json }"); const num = parseInt("abc", 10); if (isNaN(num)) throw new RangeError("NaN");} catch (err) { if (err instanceof SyntaxError) { console.error("JSON error:", err.message); } else if (err instanceof RangeError) { console.error("Range error:", err.message); } else { throw err; // re-raise unknown errors }}# Python — multiple except clausesimport json
try: data = json.loads("{ bad json }") value = int("abc")except json.JSONDecodeError as e: print(f"JSON error: {e}")except ValueError as e: print(f"Value error: {e}")except Exception as e: raise # re-raise any other exception
# You can also catch multiple types in one clause:# except (ValueError, TypeError) as e:# print(f"Either error: {e}")Custom exception classes
Section titled “Custom exception classes”// TypeScriptclass AppError extends Error { constructor( message: string, public readonly code: number ) { super(message); this.name = "AppError"; }}
try { throw new AppError("Not found", 404);} catch (err) { if (err instanceof AppError) { console.log(`[${err.code}] ${err.message}`); }}# Pythonclass AppError(Exception): def __init__(self, message: str, code: int) -> None: super().__init__(message) self.code = code
try: raise AppError("Not found", 404)except AppError as e: print(f"[{e.code}] {e}")Two Python 3.14 changes worth knowing
Section titled “Two Python 3.14 changes worth knowing”Parentheses are optional when you catch several types without binding the exception (PEP 758). If you use as, the parentheses stay required — that is what keeps the syntax unambiguous.
# Python 3.14 — no parentheses neededtry: connect_to_server()except TimeoutError, ConnectionRefusedError: print("Network error!")
# With "as", parentheses are still requiredtry: connect_to_server()except (TimeoutError, ConnectionRefusedError) as e: print(f"Network error: {e}")Leaving a finally block now warns (PEP 765). A return, break, or continue inside finally silently throws away whatever exception was in flight — a bug TypeScript developers hit too, since JavaScript behaves the same way. Python 3.14 emits a SyntaxWarning when it sees it.
def read(path: str) -> str: try: raise OSError("disk on fire") finally: return "" # SyntaxWarning: the OSError disappearsTry it
Section titled “Try it”def divide(a: float, b: float) -> float: if b == 0: raise ValueError("Cannot divide by zero") return a / b
# Successful casetry: result = divide(10, 2) print(f"10 / 2 = {result}")except ValueError as e: print(f"Error: {e}")else: print("No error occurred (else clause)")finally: print("Always runs")
print()
# Error casetry: result = divide(10, 0)except ValueError as e: print(f"Caught: {e}")else: print("This will NOT print")finally: print("Finally again")Loading Python runtime (first run only)…