[{"data":1,"prerenderedAt":144},["ShallowReactive",2],{"topic-python-exceptions":3},{"framework":4,"topic":15,"subtopics":24},{"id":5,"description":6,"extension":7,"icon":8,"meta":9,"name":10,"order":11,"slug":8,"stem":12,"tier":13,"__hash__":14},"frameworks\u002Fframeworks\u002Fpython.yml","Python interview questions across language fundamentals, data structures and common gotchas for backend, data and automation roles.","yml","python",{},"Python",3,"frameworks\u002Fpython",1,"QsijsotyAr-3rnhJDWWZmc7hE6HAhylS5t1dKpigMOA",{"id":16,"description":17,"extension":7,"frameworkSlug":8,"meta":18,"name":19,"order":20,"slug":21,"stem":22,"__hash__":23},"topics\u002Ftopics\u002Fpython-exceptions.yml","try\u002Fexcept\u002Felse\u002Ffinally, the exception hierarchy, custom exceptions and context managers — robust error handling in Python.",{},"Errors & Exceptions",6,"exceptions","topics\u002Fpython-exceptions","AxiThX7RyYVRhjW0TnsHXhYt19xLlcCrOU2utOgPrfs",[25,70,105],{"id":26,"title":27,"body":28,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":37,"navigation":38,"order":13,"path":39,"questions":40,"related":63,"seo":64,"seoDescription":65,"stem":66,"subtopic":67,"topic":19,"topicSlug":21,"updated":68,"__hash__":69},"qa\u002Fpython\u002Fexceptions\u002Fcontext-managers.md","Context Managers",{"type":29,"value":30,"toc":31},"minimark",[],{"title":32,"searchDepth":33,"depth":33,"links":34},"",2,[],"medium","md",{},true,"\u002Fpython\u002Fexceptions\u002Fcontext-managers",[41,46,50,54,59],{"id":42,"difficulty":43,"q":44,"a":45},"what-is-context-manager","easy","What is a context manager and what does the with statement do?","A **context manager** is an object that defines **setup and teardown** logic to run\naround a block of code. The **`with` statement** uses it to guarantee that the\nteardown happens — even if the block raises an exception or returns early — so you\ndon't have to write manual `try\u002Ffinally`.\n\n```python\nwith open(\"data.txt\") as f:   # __enter__ runs, returns the file\n    data = f.read()\n# __exit__ runs here automatically — the file is closed\n```\n\nThe classic use is resource management: files, network sockets, database\nconnections, and locks. Rule of thumb: any \"acquire then must-release\" pattern is\na candidate for a `with` block.\n",{"id":47,"difficulty":35,"q":48,"a":49},"enter-exit","How do __enter__ and __exit__ work?","To make a class a context manager you implement two dunder methods. **`__enter__`**\nruns at the start of the `with` block and its return value is bound to the `as`\nvariable. **`__exit__`** runs when the block ends — always — receiving the\nexception type, value, and traceback (all `None` if the block succeeded).\n\n```python\nclass Timer:\n    def __enter__(self):\n        import time; self.start = time.time()\n        return self                      # bound to 'as t'\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        import time; print(time.time() - self.start)\n        return False                     # don't suppress exceptions\n\nwith Timer() as t:\n    do_work()\n```\n\n`__exit__` always runs, which is what makes cleanup reliable. Rule of thumb:\nacquire the resource in `__enter__`, release it in `__exit__`, and `return self`\nif callers need the object.\n",{"id":51,"difficulty":35,"q":52,"a":53},"contextlib-decorator","How does contextlib.contextmanager simplify writing one?","The **`@contextlib.contextmanager`** decorator lets you write a context manager as a\n**generator** instead of a class. Code **before `yield`** is the setup (`__enter__`),\nthe **yielded value** becomes the `as` target, and code **after `yield`** is the\nteardown (`__exit__`).\n\n```python\nfrom contextlib import contextmanager\n\n@contextmanager\ndef opened(path):\n    f = open(path)          # setup\n    try:\n        yield f             # value bound to 'as'\n    finally:\n        f.close()           # teardown — runs even on error\n\nwith opened(\"data.txt\") as f:\n    print(f.read())\n```\n\nThe `try\u002Ffinally` around the `yield` is essential — without it the teardown is\nskipped when the block raises. Rule of thumb: reach for the decorator for simple,\none-off managers; write a class when you need state across multiple methods.\n",{"id":55,"difficulty":56,"q":57,"a":58},"exceptions-in-exit","hard","How does a context manager handle exceptions in __exit__?","When the `with` block raises, Python passes the exception details into `__exit__`.\nThe crucial part is the **return value**: returning a **truthy** value tells Python\nto **suppress** the exception, while returning `False`\u002F`None` lets it **propagate**\nnormally.\n\n```python\nclass Suppress:\n    def __enter__(self): return self\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        if exc_type is ValueError:\n            print(\"swallowed:\", exc_val)\n            return True          # suppress ValueError\n        return False             # re-raise anything else\n\nwith Suppress():\n    raise ValueError(\"oops\")     # swallowed, program continues\n```\n\n`contextlib.suppress(ValueError)` is the ready-made version of this pattern. Rule\nof thumb: only suppress exceptions you genuinely intend to ignore — accidentally\nreturning a truthy value hides bugs.\n",{"id":60,"difficulty":43,"q":61,"a":62},"multiple-context-managers","How do you use multiple context managers and what are real uses?","You can manage several resources in one `with` by separating them with commas (or\nusing parenthesized form in 3.10+). They are **entered left to right** and\n**exited in reverse order**, so cleanup unwinds correctly.\n\n```python\nwith open(\"in.txt\") as src, open(\"out.txt\", \"w\") as dst:\n    dst.write(src.read())\n# dst closed first, then src\n\nimport threading\nlock = threading.Lock()\nwith lock:                 # acquire on enter, release on exit\n    shared_counter += 1\n```\n\nCommon real uses: **files** (auto-close), **locks** (auto-release even on error),\n**database transactions** (commit\u002Frollback), and temporarily **changing state**\nlike `decimal.localcontext`. Rule of thumb: if you ever write `try\u002Ffinally` to\nrelease something, a context manager expresses it more clearly.\n",null,{"description":32},"Python interview questions on context managers and the with statement, __enter__\u002F__exit__, contextlib.contextmanager, exception handling in __exit__, and multiple context managers.","python\u002Fexceptions\u002Fcontext-managers","Context Managers & with","2026-06-18","_wYx3YKUE7hQadgYFrkMXwIkQXcyoJFa0Pm0YBK9cu8",{"id":71,"title":72,"body":73,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":77,"navigation":38,"order":33,"path":78,"questions":79,"related":63,"seo":100,"seoDescription":101,"stem":102,"subtopic":103,"topic":19,"topicSlug":21,"updated":68,"__hash__":104},"qa\u002Fpython\u002Fexceptions\u002Ftry-except.md","Try Except",{"type":29,"value":74,"toc":75},[],{"title":32,"searchDepth":33,"depth":33,"links":76},[],{},"\u002Fpython\u002Fexceptions\u002Ftry-except",[80,84,88,92,96],{"id":81,"difficulty":35,"q":82,"a":83},"four-clauses","What do the try, except, else, and finally clauses do and when does each run?","A full statement has four parts. **`try`** holds the code that might fail.\n**`except`** runs only if a matching exception was raised in `try`. **`else`**\nruns only if `try` finished **without** raising — it's for the \"success path\"\ncode you don't want wrapped in the `try`. **`finally`** runs **always**, whether\nthere was an exception or not, and even if you `return`\u002F`break` — it's for cleanup.\n\n```python\ntry:\n    conn = open_db()          # might raise\nexcept DBError as e:\n    log(e)                    # runs only on failure\nelse:\n    conn.commit()             # runs only on success\nfinally:\n    conn.close()              # always runs — cleanup\n```\n\nPutting the success-only code in `else` (instead of at the bottom of `try`) keeps\nthe `try` block narrow, so `except` only catches errors from the risky line.\n",{"id":85,"difficulty":35,"q":86,"a":87},"catch-multiple","How do you catch multiple exception types, and what does `as e` give you?","Group related types in a **tuple** after `except`, or use separate `except`\nclauses when each needs different handling. The `as e` binds the **exception\ninstance**, letting you inspect its message, args, or attributes.\n\n```python\ntry:\n    value = int(raw)\nexcept (ValueError, TypeError) as e:   # tuple -> one handler for both\n    print(f\"bad input: {e}\")           # e is the exception object\nexcept KeyError:                       # separate handler, different logic\n    print(\"missing key\")\n```\n\nClauses are checked **top to bottom**, and the **first match wins** — so order\nspecific exceptions before their base classes. Use the tuple form when several\ntypes share handling; use separate clauses when they don't.\n",{"id":89,"difficulty":35,"q":90,"a":91},"bare-except","Why is a bare `except:` considered bad practice?","A bare `except:` (or `except BaseException:`) catches **everything** — including\n`KeyboardInterrupt` and `SystemExit`, which are how the user Ctrl-Cs or the\nprogram exits. It also **swallows bugs** like `NameError` or `TypeError` that you'd\nrather see crash loudly, making problems invisible.\n\n```python\ntry:\n    do_work()\nexcept:                 # too broad — even Ctrl-C is caught\n    pass                # silent failure — hides real bugs\n\ntry:\n    do_work()\nexcept Exception as e:  # catches errors, not Ctrl-C \u002F SystemExit\n    log.exception(e)    # at least record what happened\n```\n\nCatch the **narrowest** exception you can actually handle. If you must catch\nbroadly, use `except Exception` (not bare), and always log rather than silently\n`pass`.\n",{"id":93,"difficulty":56,"q":94,"a":95},"finally-return","What happens when `finally` contains a `return`?","`finally` always runs, even when `try` or `except` already has a `return`. If\n`finally` itself **returns** (or raises), it **overrides** the pending return or\nexception — the value from `try`\u002F`except` is silently discarded. This is a classic\ngotcha.\n\n```python\ndef f():\n    try:\n        return 1        # value queued...\n    finally:\n        return 2        # ...but finally's return wins\nf()                     # 2, not 1\n\ndef g():\n    try:\n        raise ValueError\n    finally:\n        return \"swallowed\"   # finally return suppresses the exception!\ng()                     # \"swallowed\" — exception vanishes\n```\n\nAvoid `return`\u002F`break` inside `finally`: it masks both return values and\nexceptions. Keep `finally` for cleanup only.\n",{"id":97,"difficulty":56,"q":98,"a":99},"reraise-chaining","How do you re-raise an exception and what is exception chaining?","A bare **`raise`** (no argument) inside an `except` block **re-raises the current\nexception**, preserving its original traceback — useful for logging then letting it\npropagate. To translate one error into another while keeping the cause, use\n**`raise NewError from original`**, which sets `__cause__` and shows both in the\ntraceback.\n\n```python\ntry:\n    parse(config)\nexcept KeyError as e:\n    log.error(\"config invalid\")\n    raise                       # re-raise same exception, original traceback\n\ntry:\n    value = data[\"port\"]\nexcept KeyError as e:\n    raise ConfigError(\"missing port\") from e   # explicit chaining\n```\n\nWhen an exception is raised **inside** an `except` block without `from`, Python\nstill links it implicitly via `__context__` (\"During handling of the above...\"). Use\n`from e` to make the cause explicit, or `from None` to suppress the chain.\n",{"description":32},"Python interview questions on try\u002Fexcept\u002Felse\u002Ffinally, catching multiple exception types, why bare except is bad, finally with return, and exception chaining with raise from.","python\u002Fexceptions\u002Ftry-except","try \u002F except \u002F else \u002F finally","zypRLfxfYjZySj7ZLjRlUt8LzLvDa0sVDs3sO4N7lzk",{"id":106,"title":107,"body":108,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":112,"navigation":38,"order":11,"path":113,"questions":114,"related":63,"seo":139,"seoDescription":140,"stem":141,"subtopic":142,"topic":19,"topicSlug":21,"updated":68,"__hash__":143},"qa\u002Fpython\u002Fexceptions\u002Fcustom-exceptions.md","Custom Exceptions",{"type":29,"value":109,"toc":110},[],{"title":32,"searchDepth":33,"depth":33,"links":111},[],{},"\u002Fpython\u002Fexceptions\u002Fcustom-exceptions",[115,119,123,127,131,135],{"id":116,"difficulty":35,"q":117,"a":118},"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":120,"difficulty":43,"q":121,"a":122},"defining-custom","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":124,"difficulty":35,"q":125,"a":126},"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":128,"difficulty":35,"q":129,"a":130},"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":132,"difficulty":35,"q":133,"a":134},"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":136,"difficulty":43,"q":137,"a":138},"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",{"description":32},"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","_NsIl_DBSx_bgYPk7Jw_vU-Q07dm94XjSeGNaH_9WLM",1781808675160]