[{"data":1,"prerenderedAt":176},["ShallowReactive",2],{"topic-python-stdlib":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-stdlib.yml","pathlib and os, datetime, regular expressions and JSON\u002FCSV — the batteries-included modules every Python developer reaches for.",{},"Standard Library Essentials",12,"stdlib","topics\u002Fpython-stdlib","sRFqpDw98pJhtlo77axy-qulzRwuEEAdxjjHQKKWSGA",[25,70,105,140],{"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\u002Fstdlib\u002Fregex.md","Regex",{"type":29,"value":30,"toc":31},"minimark",[],{"title":32,"searchDepth":33,"depth":33,"links":34},"",2,[],"medium","md",{},true,"\u002Fpython\u002Fstdlib\u002Fregex",[41,46,50,54,59],{"id":42,"difficulty":43,"q":44,"a":45},"match-search-fullmatch","easy","What is the difference between re.match, re.search, and re.fullmatch?","They differ in **where** the pattern must match. `re.match` anchors at the\n**start** of the string (but not the end). `re.search` scans for the pattern\n**anywhere** in the string. `re.fullmatch` requires the pattern to match the\n**entire** string. All return a `Match` object on success or `None` on failure.\n\n```python\nimport re\nre.match(\"ab\", \"abcd\")      # match — starts with 'ab'\nre.match(\"cd\", \"abcd\")      # None  — not at the start\nre.search(\"cd\", \"abcd\")     # match — found anywhere\nre.fullmatch(\"ab\", \"abcd\")  # None  — must match the whole string\nre.fullmatch(\"abcd\", \"abcd\")# match\n```\n\nA common bug is using `match` expecting whole-string validation — it only\nanchors the start. Rule of thumb: use `search` to find, `fullmatch` to\nvalidate, and `match` only when you specifically mean \"begins with\".\n",{"id":47,"difficulty":35,"q":48,"a":49},"groups-named-groups","How do capture groups and named groups work?","Parentheses `( )` create a **capture group** you retrieve by **number**\n(1-based; group 0 is the whole match). `(?P\u003Cname>...)` creates a **named\ngroup** you retrieve by name — far more readable. `(?:...)` groups **without\ncapturing** when you only need it for grouping\u002Falternation.\n\n```python\nimport re\nm = re.search(r\"(\\d{4})-(\\d{2})\", \"2026-06\")\nm.group(0)   # '2026-06'  — whole match\nm.group(1)   # '2026'     — first group\nm.groups()   # ('2026', '06')\n\nm = re.search(r\"(?P\u003Cyear>\\d{4})-(?P\u003Cmonth>\\d{2})\", \"2026-06\")\nm.group(\"year\")   # '2026'\nm.groupdict()     # {'year': '2026', 'month': '06'}\n```\n\nNamed groups make patterns self-documenting and resilient to reordering.\nRule of thumb: use `(?P\u003Cname>...)` for anything you'll extract, and\n`(?:...)` when grouping is structural only.\n",{"id":51,"difficulty":35,"q":52,"a":53},"re-compile-why","What does re.compile do, and why would you use it?","`re.compile(pattern)` builds a **reusable pattern object** once, then you call\nmethods (`.search`, `.match`, `.findall`, `.sub`) on it. The module-level\nfunctions actually compile internally and **cache** recent patterns, so the\nmain win is **clarity and reuse** — plus a small speedup when a pattern is\nused **many times in a loop**.\n\n```python\nimport re\nDATE = re.compile(r\"(?P\u003Cyear>\\d{4})-(?P\u003Cmonth>\\d{2})\")  # compile once\n\nfor line in lines:\n    m = DATE.search(line)   # reuse the compiled object\n    if m:\n        print(m.group(\"year\"))\n```\n\nIt also lets you attach **flags** (e.g. `re.IGNORECASE`, `re.VERBOSE`) in one\nplace. Rule of thumb: compile patterns used repeatedly or shared across a\nmodule; for one-off use the module functions are fine.\n",{"id":55,"difficulty":56,"q":57,"a":58},"greedy-vs-lazy","hard","What is the difference between greedy and non-greedy matching?","By default quantifiers (`*`, `+`, `?`, `{m,n}`) are **greedy** — they match as\n**much** as possible, then backtrack. Adding a trailing `?` makes them\n**non-greedy** (lazy) — they match as **little** as possible. This matters\nhugely when a delimiter can appear multiple times.\n\n```python\nimport re\ntext = \"\u003Ca>\u003Cb>\"\nre.search(r\"\u003C.*>\", text).group()    # '\u003Ca>\u003Cb>'  — greedy, grabs everything\nre.search(r\"\u003C.*?>\", text).group()   # '\u003Ca>'     — lazy, stops at first '>'\n```\n\nGreedy patterns over-matching is a classic \"regex ate too much\" bug. Rule of\nthumb: when matching content **between delimiters**, reach for the lazy `*?`\n\u002F `+?` (or a negated character class like `[^>]*`).\n",{"id":60,"difficulty":35,"q":61,"a":62},"re-sub-raw-strings","How does re.sub work, and why use raw strings for patterns?","`re.sub(pattern, repl, string)` returns a **new** string with all matches\nreplaced. The replacement can reference captured groups with `\\1` or\n`\\g\u003Cname>`, or be a **function** that receives each `Match` for dynamic\nreplacement. You should write patterns as **raw strings** (`r\"...\"`) so that\nbackslash escapes like `\\d` and `\\b` reach the regex engine instead of being\ninterpreted by Python first.\n\n```python\nimport re\nre.sub(r\"\\s+\", \" \", \"a   b\\tc\")          # 'a b c'  — collapse whitespace\nre.sub(r\"(\\d{4})-(\\d{2})\", r\"\\2\u002F\\1\", \"2026-06\")  # '06\u002F2026' — reorder groups\nre.sub(r\"\\d+\", lambda m: f\"[{m.group()}]\", \"x9\")  # 'x[9]' — function repl\n\n\"\\d\"     # in a normal string this is an invalid escape (warns)\nr\"\\d\"    # raw string — passes \\d straight to the engine\n```\n\nWithout `r\"\"`, `\"\\b\"` becomes a backspace character, not a word boundary —\na subtle, hard-to-spot bug. Rule of thumb: **always** prefix regex patterns\nwith `r`.\n",null,{"description":32},"Python interview questions on the re module — match vs search vs fullmatch, capture and named groups, re.compile, greedy vs non-greedy, re.sub, and raw strings.","python\u002Fstdlib\u002Fregex","Regular Expressions","2026-06-18","tGHa2xgx5-BCvqtnwBZ867ytagB6ZPf257IKaZ2rmW0",{"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\u002Fstdlib\u002Ffiles-pathlib.md","Files Pathlib",{"type":29,"value":74,"toc":75},[],{"title":32,"searchDepth":33,"depth":33,"links":76},[],{},"\u002Fpython\u002Fstdlib\u002Ffiles-pathlib",[80,84,88,92,96],{"id":81,"difficulty":43,"q":82,"a":83},"with-open","Why open files with the `with` statement?","`with open(...)` uses the file as a **context manager**, which **guarantees the file\nis closed** when the block exits — even if an exception is raised. Without it you\nmust remember to call `.close()` manually, and a crash mid-block leaks the handle.\n\n```python\nwith open(\"data.txt\") as f:      # f.close() is automatic\n    contents = f.read()\n# file is closed here, even on error\n\nf = open(\"data.txt\")             # manual style — fragile\ntry:\n    contents = f.read()\nfinally:\n    f.close()\n```\n\nLeaked handles can exhaust OS file descriptors and leave buffered writes unflushed.\nAlways prefer `with` for any resource that needs cleanup (files, locks, sockets).\n",{"id":85,"difficulty":35,"q":86,"a":87},"lazy-iteration","What is the difference between iterating a file and read()\u002Freadlines()?","A file object is its own **iterator**, yielding **one line at a time** and holding\nonly that line in memory. `read()` loads the **entire file** into a single string,\nand `readlines()` loads **all lines into a list** — both can blow up memory on large\nfiles.\n\n```python\nwith open(\"huge.log\") as f:\n    for line in f:               # lazy — one line in memory at a time\n        process(line)\n\nwith open(\"huge.log\") as f:\n    data = f.read()              # whole file as one string\n    lines = f.readlines()        # whole file as a list of strings\n```\n\nIterating is the idiomatic, memory-safe way to process big files line by line.\nReserve `read()`\u002F`readlines()` for small files where you genuinely need the whole\ncontent at once.\n",{"id":89,"difficulty":35,"q":90,"a":91},"text-binary-mode","What is the difference between text and binary mode, and why specify encoding?","**Text mode** (`\"r\"`, the default) decodes bytes into `str` using an **encoding** and\nnormalizes newlines. **Binary mode** (`\"rb\"`\u002F`\"wb\"`) reads and writes raw `bytes`\nwith no decoding — required for images, archives, or any non-text data. In text\nmode you should pass **`encoding=`** explicitly, because the default is\nplatform-dependent.\n\n```python\nwith open(\"notes.txt\", \"r\", encoding=\"utf-8\") as f:\n    text: str = f.read()         # decoded to str\n\nwith open(\"photo.jpg\", \"rb\") as f:\n    raw: bytes = f.read()        # raw bytes, no decoding\n```\n\nRelying on the default encoding is a classic cross-platform bug (UTF-8 on Linux\u002FMac,\noften a legacy codepage on Windows). Always specify `encoding=\"utf-8\"` for text, and\nuse binary mode for everything that isn't text.\n",{"id":93,"difficulty":35,"q":94,"a":95},"pathlib-vs-os-path","What is pathlib.Path and how does it compare to os.path?","**`pathlib.Path`** is the modern, object-oriented way to handle filesystem paths. A\n`Path` is an object with **methods and operators**, whereas the older **`os.path`**\nmodule is a collection of **string-based functions**. Path's `\u002F` operator joins\nsegments cleanly and works across operating systems.\n\n```python\nfrom pathlib import Path\n\np = Path(\"data\") \u002F \"logs\" \u002F \"app.log\"   # join with \u002F\np.exists()\np.suffix                                 # \".log\"\np.stem                                   # \"app\"\np.read_text(encoding=\"utf-8\")            # one-liner read\n\nimport os.path\nold = os.path.join(\"data\", \"logs\", \"app.log\")\nos.path.exists(old)\n```\n\n`pathlib` is generally preferred for new code: it's more readable and bundles\ncommon operations (`read_text`, `mkdir`, `glob`) as methods. Use `os.path` mainly\nwhen working with existing string-based APIs.\n",{"id":97,"difficulty":35,"q":98,"a":99},"globbing-path-methods","How do you find files with globbing using pathlib?","Use **`Path.glob(pattern)`** for matches in one directory and **`Path.rglob(pattern)`**\n(or `glob(\"**\u002F...\")`) to recurse into subdirectories. Both return a **lazy generator**\nof `Path` objects, where `*` matches any characters and `**` matches directories\nrecursively.\n\n```python\nfrom pathlib import Path\n\nroot = Path(\"project\")\nfor py in root.glob(\"*.py\"):         # top level only\n    print(py.name)\n\nfor py in root.rglob(\"*.py\"):        # all subdirectories too\n    print(py)\n\nroot.mkdir(parents=True, exist_ok=True)  # create dirs safely\n[p.name for p in root.iterdir()]         # list directory contents\n```\n\nOther handy `Path` methods: `iterdir()` (list a directory), `is_file()`\u002F`is_dir()`,\n`mkdir()`, `unlink()` (delete), and `with_suffix()`. Globbing returns generators, so\nwrap in `list(...)` if you need a concrete collection.\n",{"description":32},"Python interview questions on open() and the with statement, lazy file iteration, text vs binary mode and encoding, pathlib.Path vs os.path, and globbing.","python\u002Fstdlib\u002Ffiles-pathlib","Files, pathlib & os","NoZp_VMdm_N8l_uZ9iKq2ZIl7xuq4gVgtZ6dt2hEatE",{"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":135,"seoDescription":136,"stem":137,"subtopic":138,"topic":19,"topicSlug":21,"updated":68,"__hash__":139},"qa\u002Fpython\u002Fstdlib\u002Fdatetime.md","Datetime",{"type":29,"value":109,"toc":110},[],{"title":32,"searchDepth":33,"depth":33,"links":111},[],{},"\u002Fpython\u002Fstdlib\u002Fdatetime",[115,119,123,127,131],{"id":116,"difficulty":43,"q":117,"a":118},"datetime-date-time","What is the difference between datetime, date, and time?","The `datetime` module provides three core types. **`date`** holds a calendar date\n(year, month, day) with **no time**. **`time`** holds a time of day (hour, minute,\nsecond, microsecond) with **no date**. **`datetime`** combines **both** into a\nsingle timestamp.\n\n```python\nfrom datetime import date, time, datetime\n\nd = date(2026, 6, 18)               # just the date\nt = time(14, 30, 0)                 # just the time of day\ndt = datetime(2026, 6, 18, 14, 30)  # date + time together\n\ndt.date()                           # -> date(2026, 6, 18)\ndt.time()                           # -> time(14, 30)\ndate.today()                        # current date\n```\n\nUse `date` for things like birthdays or due dates where time is irrelevant, `time`\nfor a recurring clock time, and `datetime` for actual events\u002Ftimestamps. Most\nreal-world work uses `datetime`.\n",{"id":120,"difficulty":56,"q":121,"a":122},"naive-aware-zoneinfo","What is the difference between naive and timezone-aware datetimes?","A **naive** datetime has **no timezone info** (`tzinfo` is `None`) — it's just wall\nclock numbers with no reference point, so it's ambiguous. An **aware** datetime\ncarries a `tzinfo`, pinning it to an actual instant. Use the stdlib **`zoneinfo`**\nmodule (Python 3.9+) to attach real IANA timezones.\n\n```python\nfrom datetime import datetime\nfrom zoneinfo import ZoneInfo\n\nnaive = datetime(2026, 6, 18, 14, 30)          # ambiguous — no tz\naware = datetime(2026, 6, 18, 14, 30,\n                 tzinfo=ZoneInfo(\"America\u002FNew_York\"))\n\nutc = aware.astimezone(ZoneInfo(\"UTC\"))        # convert between zones\n```\n\nYou **can't compare or subtract** a naive and an aware datetime — it raises\n`TypeError`. Best practice: store and compute in **UTC-aware** datetimes, and convert\nto local zones only for display.\n",{"id":124,"difficulty":35,"q":125,"a":126},"strftime-strptime","What is the difference between strftime and strptime?","They are inverses. **`strftime`** (\"string **f**rom time\") **formats** a datetime\n**into** a string using format codes. **`strptime`** (\"string **p**arse time\")\n**parses** a string **into** a datetime using a matching format.\n\n```python\nfrom datetime import datetime\n\ndt = datetime(2026, 6, 18, 14, 30)\ns = dt.strftime(\"%Y-%m-%d %H:%M\")       # datetime -> \"2026-06-18 14:30\"\n\nparsed = datetime.strptime(\"2026-06-18 14:30\",\n                           \"%Y-%m-%d %H:%M\")  # str -> datetime\n```\n\nCommon codes: `%Y` (4-digit year), `%m` (month), `%d` (day), `%H` (24-hour),\n`%M` (minute), `%S` (second). To remember: **f** = format (out), **p** = parse (in).\nFor standard ISO strings, `datetime.fromisoformat()` \u002F `.isoformat()` are simpler.\n",{"id":128,"difficulty":35,"q":129,"a":130},"timedelta-arithmetic","How does timedelta arithmetic work?","A **`timedelta`** represents a **duration** — a difference between two points in time.\nSubtracting two datetimes yields a `timedelta`; adding a `timedelta` to a datetime\nshifts it. A `timedelta` stores days, seconds, and microseconds.\n\n```python\nfrom datetime import datetime, timedelta\n\nstart = datetime(2026, 6, 18, 9, 0)\nend   = datetime(2026, 6, 18, 17, 30)\n\nworked = end - start              # timedelta(seconds=30600)\nworked.total_seconds()            # 30600.0\nworked.seconds \u002F\u002F 3600            # 8 (hours portion)\n\ntomorrow = start + timedelta(days=1)      # shift forward\nweek_ago = start - timedelta(weeks=1)     # shift back\n```\n\nUse `total_seconds()` to get the whole duration as a number (the `.seconds`\nattribute is only the sub-day part). `timedelta` makes date math safe — it correctly\nrolls over months and years.\n",{"id":132,"difficulty":56,"q":133,"a":134},"now-vs-utcnow","What is the pitfall with datetime.now() vs utcnow()?","The big trap: **both `datetime.now()` and the old `datetime.utcnow()` return *naive*\ndatetimes**. `now()` gives local wall time, `utcnow()` gives the UTC wall time — but\n**neither attaches a tzinfo**, so a `utcnow()` value silently *looks* like local\ntime and corrupts later conversions. `utcnow()` is **deprecated** in modern Python.\n\n```python\nfrom datetime import datetime\nfrom zoneinfo import ZoneInfo\n\ndatetime.now()                       # naive, local time — ambiguous\ndatetime.utcnow()                    # naive, but labelled nothing! (deprecated)\n\n# correct: an AWARE UTC timestamp\nnow_utc = datetime.now(ZoneInfo(\"UTC\"))\nlocal = datetime.now(ZoneInfo(\"America\u002FNew_York\"))\n```\n\nRule of thumb: **always pass a timezone to `now()`** to get an aware datetime, and\navoid `utcnow()` entirely. Store timestamps as UTC-aware and convert for display.\n",{"description":32},"Python interview questions on datetime vs date vs time, naive vs timezone-aware datetimes with zoneinfo, strftime\u002Fstrptime, timedelta arithmetic, and the now() vs utcnow() pitfall.","python\u002Fstdlib\u002Fdatetime","datetime","5GeL0A_Cp3gxfR8_dMsYRrPzndiAo9KQrpPZqTy-QDE",{"id":141,"title":142,"body":143,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":147,"navigation":38,"order":148,"path":149,"questions":150,"related":63,"seo":171,"seoDescription":172,"stem":173,"subtopic":174,"topic":19,"topicSlug":21,"updated":68,"__hash__":175},"qa\u002Fpython\u002Fstdlib\u002Fserialization.md","Serialization",{"type":29,"value":144,"toc":145},[],{"title":32,"searchDepth":33,"depth":33,"links":146},[],{},4,"\u002Fpython\u002Fstdlib\u002Fserialization",[151,155,159,163,167],{"id":152,"difficulty":43,"q":153,"a":154},"json-dumps-loads","How do json.dumps and json.loads work, and how do Python types map to JSON?","**`json.dumps`** serializes a Python object **to** a JSON string; **`json.loads`**\nparses a JSON string **back** into Python objects. The `dump`\u002F`load` variants\n(no `s`) work with file objects instead. The conversion follows a fixed type\nmapping.\n\n```python\nimport json\n\ndata = {\"name\": \"Ada\", \"age\": 36, \"tags\": [\"math\"], \"active\": True}\ns = json.dumps(data)            # dict -> JSON string\nback = json.loads(s)            # JSON string -> dict\n\nwith open(\"out.json\", \"w\") as f:\n    json.dump(data, f)          # write to file\n```\n\nThe mapping: `dict`->object, `list`\u002F`tuple`->array, `str`->string, `int`\u002F`float`\n->number, `True`\u002F`False`->`true`\u002F`false`, `None`->`null`. Note **tuples become\narrays** (you get a list back), and **dict keys are coerced to strings**. JSON has\nno native date, set, or bytes type.\n",{"id":156,"difficulty":35,"q":157,"a":158},"json-custom-encoding","How do you serialize an object JSON doesn't support by default?","Unsupported types raise `TypeError: ... is not JSON serializable`. The two standard\nfixes are the **`default=` callback** (a function called for any unserializable\nobject, returning a JSON-friendly substitute) or a custom **`JSONEncoder` subclass**\npassed via **`cls=`**.\n\n```python\nimport json\nfrom datetime import datetime\n\ndef encode(obj):\n    if isinstance(obj, datetime):\n        return obj.isoformat()        # turn it into a string\n    raise TypeError(f\"not serializable: {type(obj)}\")\n\njson.dumps({\"when\": datetime.now()}, default=encode)\n\nclass MyEncoder(json.JSONEncoder):    # the class-based alternative\n    def default(self, obj):\n        if isinstance(obj, set):\n            return list(obj)\n        return super().default(obj)\njson.dumps({1, 2, 3}, cls=MyEncoder)\n```\n\nUse `default=` for a quick one-off; subclass `JSONEncoder` when you want reusable\nencoding logic. On the way back, use `object_hook` in `loads` to reconstruct custom\ntypes.\n",{"id":160,"difficulty":35,"q":161,"a":162},"csv-reader-dictreader","What is the difference between csv.reader and csv.DictReader?","Both read CSV files, but the row format differs. **`csv.reader`** yields each row as\na **list of strings** indexed by position. **`csv.DictReader`** treats the first row\nas **headers** and yields each row as a **dict** keyed by column name — far more\nreadable and robust to column reordering.\n\n```python\nimport csv\n\nwith open(\"people.csv\", newline=\"\") as f:\n    for row in csv.reader(f):\n        print(row[0], row[1])         # positional — brittle\n\nwith open(\"people.csv\", newline=\"\") as f:\n    for row in csv.DictReader(f):\n        print(row[\"name\"], row[\"age\"])  # by header — clear\n```\n\nAlways open CSV files with **`newline=\"\"`** to let the `csv` module handle line\nendings correctly. Prefer `DictReader`\u002F`DictWriter` for named-column access; use the\nplain `reader` for headerless or purely positional data.\n",{"id":164,"difficulty":35,"q":165,"a":166},"pickle-vs-json","What is the difference between pickle and json, and what is the security warning?","**`json`** is a **text**, language-independent format for **simple data** (dicts,\nlists, numbers, strings). **`pickle`** is a **binary**, Python-specific format that\ncan serialize **almost any Python object** (custom classes, functions references,\nnested objects). The crucial caveat: **never unpickle untrusted data**.\n\n```python\nimport json, pickle\n\njson.dumps({\"x\": 1})              # \"{\\\"x\\\": 1}\" — readable, portable\npickle.dumps({\"x\": 1})            # b'\\x80\\x04...' — binary, Python-only\n\n# DANGER: unpickling runs arbitrary code embedded in the data\npickle.loads(untrusted_bytes)     # can execute malicious payloads!\n```\n\n`pickle.loads` can **execute arbitrary code** during deserialization, so it's a\nremote-code-execution risk on attacker-controlled input. Rule of thumb: use **json**\nfor config, APIs, and anything crossing a trust boundary; use **pickle** only for\ntrusted, internal Python-to-Python data (e.g. caches you wrote yourself).\n",{"id":168,"difficulty":35,"q":169,"a":170},"serializing-datetimes","How do you serialize datetimes to JSON and back?","JSON has **no date type**, so a `datetime` must be converted to a **string** — the\nISO 8601 format via **`.isoformat()`** is the standard choice because it's\nunambiguous and parseable. On the way out use `default=`; on the way back parse the\nstring with `datetime.fromisoformat()`.\n\n```python\nimport json\nfrom datetime import datetime\n\nevent = {\"name\": \"launch\", \"at\": datetime(2026, 6, 18, 14, 30)}\n\ntext = json.dumps(event, default=lambda o: o.isoformat())\n# '{\"name\": \"launch\", \"at\": \"2026-06-18T14:30:00\"}'\n\nraw = json.loads(text)\nraw[\"at\"] = datetime.fromisoformat(raw[\"at\"])   # back to datetime\n```\n\nJSON can't tell a date-string from an ordinary string, so you must know which fields\nto re-parse (or use `object_hook`). Prefer ISO strings in **UTC** for portability,\nand convert to local time only at display.\n",{"description":32},"Python interview questions on json.dumps\u002Floads and type mapping, custom JSON encoding, csv reader vs DictReader, pickle vs json and pickle security, and serializing datetimes.","python\u002Fstdlib\u002Fserialization","JSON, CSV & pickle","viTtNO-ARfmO9ag13muRGsYBkN9JO5C_NMhcGlPbP1U",1781808675696]