[{"data":1,"prerenderedAt":66},["ShallowReactive",2],{"qa-\u002Fpython\u002Fexceptions\u002Fcustom-exceptions":3},{"page":4,"siblings":57,"blog":48},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":48,"seo":49,"seoDescription":50,"stem":51,"subtopic":52,"topic":53,"topicSlug":54,"updated":55,"__hash__":56},"qa\u002Fpython\u002Fexceptions\u002Fcustom-exceptions.md","Custom Exceptions",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Python","python",{},true,3,"\u002Fpython\u002Fexceptions\u002Fcustom-exceptions",[23,27,32,36,40,44],{"id":24,"difficulty":14,"q":25,"a":26},"hierarchy","What is the Python exception hierarchy and why shouldn't you catch BaseException?","All exceptions inherit from **`BaseException`** at the root. Directly under it sit a\nfew special ones — **`SystemExit`**, **`KeyboardInterrupt`**, and\n**`GeneratorExit`** — that are **not** meant to be caught by normal error handling.\nEverything you'd normally catch (and every built-in error like `ValueError`)\ndescends from **`Exception`**, which is itself a child of `BaseException`.\n\n```python\n# BaseException\n#  ├── SystemExit\n#  ├── KeyboardInterrupt\n#  └── Exception          \u003C- catch THIS, not BaseException\n#       ├── ValueError\n#       ├── KeyError\n#       └── ...\n```\n\nCatching `BaseException` (or a bare `except:`) traps `KeyboardInterrupt` and\n`SystemExit`, so Ctrl-C and clean shutdowns stop working. **Catch `Exception`**\n(or narrower) and let the system-level ones propagate.\n",{"id":28,"difficulty":29,"q":30,"a":31},"defining-custom","easy","How do you define a custom exception class?","Subclass **`Exception`** (almost never `BaseException`). The simplest custom\nexception needs no body at all — `pass` is enough, since it inherits message\nhandling from `Exception`.\n\n```python\nclass ConfigError(Exception):\n    \"\"\"Raised when configuration is invalid.\"\"\"\n\nraise ConfigError(\"missing 'port' key\")\n\ntry:\n    ...\nexcept ConfigError as e:\n    print(e)            # missing 'port' key\n```\n\nGive the class a clear, specific name ending in `Error`, and a docstring describing\nwhen it's raised. Even an empty subclass is valuable because it lets callers catch\n*your* error specifically instead of a generic `Exception`.\n",{"id":33,"difficulty":14,"q":34,"a":35},"when-to-subclass","When and why should you create custom exceptions?","Create a custom exception when callers need to **distinguish your error** from\nothers and handle it differently. A common pattern is a single **base exception for\nyour library\u002Fapp**, with specific subclasses beneath it — so users can catch the\nbase to handle \"anything from this library\" or a subclass for fine-grained control.\n\n```python\nclass PaymentError(Exception):\n    \"\"\"Base for all payment problems.\"\"\"\n\nclass CardDeclined(PaymentError): pass\nclass InsufficientFunds(PaymentError): pass\n\ntry:\n    charge(card)\nexcept InsufficientFunds:\n    retry_later()\nexcept PaymentError:          # catches any other payment error\n    alert_support()\n```\n\nDon't invent a custom exception when a built-in already fits — bad input is a\n`ValueError`, a missing key is a `KeyError`. Add your own only when it carries\nmeaning the built-ins can't.\n",{"id":37,"difficulty":14,"q":38,"a":39},"passing-args","How do you pass arguments and messages to an exception?","Arguments passed to an exception are stored in its **`.args`** tuple, and the first\none becomes the string returned by `str(exception)`. To attach **structured data**,\nadd attributes in a custom `__init__` (and call `super().__init__()` so the message\nstill works).\n\n```python\nraise ValueError(\"bad value\", 42)\n# e.args == (\"bad value\", 42)\n\nclass ApiError(Exception):\n    def __init__(self, message, status_code):\n        super().__init__(message)   # sets the message \u002F .args\n        self.status_code = status_code\n\ntry:\n    raise ApiError(\"not found\", 404)\nexcept ApiError as e:\n    print(e, e.status_code)         # not found 404\n```\n\nUse a plain message for simple cases; add attributes when handlers need to inspect\ndetails (like an HTTP status or the offending value) rather than parse the text.\n",{"id":41,"difficulty":14,"q":42,"a":43},"base-catches-subclasses","Why does catching a base exception class also catch its subclasses?","`except` matches via **`isinstance`**, so a handler for a base class catches the\nbase **and every subclass**. That's why `except Exception` catches almost\neverything, and why ordering matters: put **specific subclasses before** their base,\nor the base will intercept them first.\n\n```python\nclass AppError(Exception): pass\nclass NotFound(AppError): pass\n\ntry:\n    raise NotFound(\"user\")\nexcept AppError:            # matches — NotFound IS-A AppError\n    print(\"caught by base\")\n\ntry:\n    raise NotFound(\"user\")\nexcept AppError:            # this runs first...\n    print(\"base\")\nexcept NotFound:            # ...so this is unreachable!\n    print(\"specific\")\n```\n\nOrder `except` clauses **most-specific first**. The same rule is why\n`except Exception` should come last among your handlers.\n",{"id":45,"difficulty":29,"q":46,"a":47},"common-builtins","What are some common built-in exceptions and when are they raised?","Knowing the standard ones lets you catch precisely and raise the *right* error.\n**`ValueError`** — right type, wrong value (`int(\"abc\")`). **`TypeError`** — wrong\ntype entirely (`\"x\" + 1`). **`KeyError`** — missing dict key. **`IndexError`** —\nlist index out of range. **`AttributeError`** — missing attribute. **`KeyError`**\nand **`IndexError`** both subclass **`LookupError`**.\n\n```python\nint(\"abc\")          # ValueError\n\"x\" + 1             # TypeError\n{\"a\": 1}[\"b\"]       # KeyError\n[1, 2][5]           # IndexError\nNone.foo            # AttributeError\n```\n\nRaise the built-in that best describes the problem instead of a generic\n`Exception` — `ValueError` for bad arguments, `TypeError` for wrong types — so\ncallers can handle them idiomatically.\n",null,{"description":11},"Python interview questions on the exception hierarchy, BaseException vs Exception, defining custom exception classes, passing messages, and how catching a base class catches its subclasses.","python\u002Fexceptions\u002Fcustom-exceptions","Custom Exceptions & the Hierarchy","Errors & Exceptions","exceptions","2026-06-18","_NsIl_DBSx_bgYPk7Jw_vU-Q07dm94XjSeGNaH_9WLM",[58,62,65],{"subtopic":59,"path":60,"order":61},"Context Managers & with","\u002Fpython\u002Fexceptions\u002Fcontext-managers",1,{"subtopic":63,"path":64,"order":12},"try \u002F except \u002F else \u002F finally","\u002Fpython\u002Fexceptions\u002Ftry-except",{"subtopic":52,"path":21,"order":20},1781808680916]