Errors
Sere exceptions are values with a class hierarchy rooted at Exception. try needs except and/or finally. Optional else runs when nothing was raised.
try:
raise TypeError("nope")
except TypeError as e:
print(e.message)except Type matches that class and its subclasses. Bare except: catches everything. as e binds an instance with .message.
Raising
class Boom(ValueError):
pass
raise Boom("bad")
raise "boom" # Exception
raise TypeError # empty message
assert False, "fail" # AssertionError, catchableraise stringifies the first constructor argument (or a bare str). Bare raise uses an empty Exception. panic("msg") still aborts — it is not catchable control flow.
Builtin classes
All subclass Exception:
SyntaxError, IndentationError, NameError, AttributeError, TypeError, IndexError, ImportError, ValueError, AssertionError, PermissionError, RuntimeError, RecursionError, NotImplementedError.
The compiler also uses these names as diagnostic codes: error[NameError]: unknown name 'foo'. That is the same catalog, two surfaces. See Diagnostics.
Prelude macros
todo!("not yet")
unreachable!()
dbg!(total) # prints and yields totaltodo! and unreachable! are for paths that must not run. They are not a substitute for raise.
defer vs finally
defer runs on function return, in reverse order. finally runs when leaving the try, including via raise. Use finally for exception-safe cleanup; use defer for the happy-path / every-return path inside one function.