skip to content

Standard Library

The batteries you reach for daily: re, pathlib and open(), json and csv, datetime with zoneinfo, subprocess, and logging. Interviewers probe which module you pick and the trap each one hides.

part ofPythonoverview, primer and where to startread it →
on this pageshow

explore

questions

156 · 10 sections

How do you name a capture group in a Python re pattern, and what does .groupdict() return?

level: juniorimportance: must knowfreq 62%
basics
~10 s

Write (?P<name>...) to name a group. The match object then exposes it as m.group('name'), and m.groupdict() returns a dict mapping every named group to the text it captured; unnamed numbered groups are not included.

open as a page

Why are regex patterns in Python written as raw strings like r"\d+"?

level: juniorimportance: must knowfreq 60%
basics
~10 s

A backslash means something to both the string-literal parser and the regex engine. A raw literal stops Python consuming it first, so the engine sees what you typed. Otherwise you must double every backslash.

open as a page

What is the difference between re.match, re.search and re.fullmatch?

level: juniorimportance: must knowfreq 75%
basics
~20 s

re.match only tries the pattern at the start of the string, re.search scans forward and returns the first match anywhere, and re.fullmatch requires the pattern to consume the whole string. All three return a Match object or None.

open as a page

What is the difference between `.*` and `.*?` in a Python `re` pattern?

level: juniorimportance: must knowfreq 70%
basics
~20 s

.* is greedy: it grabs as much text as it can, then gives characters back only when the rest of the pattern fails. .*? is lazy: it starts empty and grows one character at a time, only when forced.

open as a page

Why does `re.search(r'(a+)+$', 'a'*30 + '!')` take exponential time?

level: middleimportance: must knowfreq 50%
basics
~20 s

The inner a+ and the outer + can carve the run of as up in about 2^n ways. The trailing ! makes $ fail, so the backtracking engine must try every one of those splits before reporting no match.

open as a page

What do open()'s 'w', 'a' and 'x' modes each do to an existing file?

level: juniorimportance: must knowfreq 70%
basics
~10 s

'w' truncates the file to zero bytes, creating it if absent. 'a' leaves the contents alone and writes at the end. 'x' refuses to touch an existing file and raises FileExistsError.

open as a page

How does pathlib.Path use the / operator to join paths, and what do .name, .stem and .parent return?

level: juniorimportance: must knowfreq 72%
basics
~10 s

pathlib.Path overloads the division operator, so Path("exports") / "schedule.json" builds a new path object with the right separator. On that result .name is "schedule.json", .stem is "schedule", .suffix is ".json" and .parent is Path("exports").

open as a page

When do you use tempfile.NamedTemporaryFile, TemporaryDirectory or mkstemp?

level: juniorimportance: must knowfreq 58%
basics
~10 s

tempfile.TemporaryDirectory gives a whole scratch directory removed when its with-block ends. tempfile.NamedTemporaryFile gives one auto-deleted open file. tempfile.mkstemp gives a raw file descriptor plus a path you must close and unlink yourself.

open as a page

How does the write-to-temp-then-os.replace pattern make a file update atomic?

level: middleimportance: must knowfreq 45%
basics
~20 s

The new contents go into a temporary file in the target's own directory; os.replace(tmp, target) then swaps the directory entry in one step, so a reader sees either the whole old file or the whole new one.

open as a page

Which encoding does open() use in text mode when encoding= is omitted?

level: middleimportance: must knowfreq 60%
basics
~20 s

On Python 3.14 a text-mode open() with no encoding= uses the machine's locale encoding, not UTF-8. The same script can read a file on one machine and raise UnicodeDecodeError on another, so pass encoding= explicitly.

open as a page

Why is str.split(',') wrong for parsing a CSV line, and what does csv.reader do instead?

level: juniorimportance: must knowfreq 58%
basics
~20 s

A comma inside a quoted field is data, not a separator, so str.split(',') tears such a row apart. csv.reader runs the quoting state machine over the file object and yields each record as a list of strings.

open as a page

How do json.load, json.loads, json.dump and json.dumps differ?

level: juniorimportance: must knowfreq 75%
basics
~20 s

The trailing s means string. json.loads parses JSON text already in memory and json.load reads it from an open file object; json.dumps returns a JSON string, while json.dump writes that text straight into a file object.

open as a page

Why does pickle.loads() run arbitrary code when handed untrusted bytes?

level: juniorimportance: must knowfreq 70%
basics
~20 s

A pickle stream is a small program for a stack machine, not a data document. Its opcodes can import any importable name and call it, so pickle.loads on attacker-controlled bytes runs the attacker's code before you inspect any value.

open as a page

Why does tomllib.load require a file opened in binary mode ('rb')?

level: juniorimportance: must knowfreq 50%
basics
~20 s

tomllib.load reads bytes and decodes them as UTF-8 itself, because a TOML document is UTF-8 by definition. A file opened in text mode has already been decoded with the platform encoding, so load raises TypeError; open the path with 'rb'.

open as a page

How do Element.find, findall and iter differ in xml.etree.ElementTree?

level: juniorimportance: must knowfreq 45%
basics
~20 s

Element.find returns the first match or None, findall returns a list of every match at that path, and iter walks the whole subtree recursively, including the element itself, yielding each element with the given tag.

open as a page

Why measure elapsed time with time.monotonic() instead of time.time() in Python?

level: juniorimportance: must knowfreq 60%
basics
~20 s

time.monotonic() only ever moves forward, so the difference between two readings is a true duration. time.time() names a wall-clock instant, and NTP or an operator can step it forwards or backwards, corrupting any elapsed-time calculation.

open as a page

What makes a Python datetime object aware rather than naive?

level: juniorimportance: must knowfreq 70%
basics
~10 s

A datetime is aware when it carries a tzinfo whose utcoffset() returns a real offset; otherwise it is naive. datetime.datetime(2026, 9, 5, 12, 0) is naive, and passing tzinfo=datetime.timezone.utc makes the same reading aware.

open as a page

Why use zoneinfo.ZoneInfo('Europe/Berlin') instead of a fixed UTC+1 offset?

level: juniorimportance: must knowfreq 52%
basics
~20 s

ZoneInfo('Europe/Berlin') carries that region's full IANA rule history, so the offset it reports depends on the moment in question. A datetime.timezone built from a timedelta is one frozen number and is wrong for part of every year.

open as a page

What does the fold attribute on a datetime.datetime mean during a DST transition?

level: middleimportance: must knowfreq 45%
basics
~20 s

fold is a 0-or-1 flag that says which pass through a repeated local wall time you mean: 0 the first occurrence, 1 the second. It defaults to 0 and only changes anything across an offset change.

open as a page

Why does comparing a naive and an aware Python datetime raise TypeError?

level: middleimportance: must knowfreq 60%
basics
~20 s

A naive datetime states no offset, so there is no shared instant to order against an aware one, and Python refuses to guess. Ordering and subtraction raise TypeError; equality does not raise — it quietly returns False.

open as a page

In argparse, what distinguishes a positional argument from an optional one?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The leading dashes decide. add_argument("dataset") defines a positional argument: required, matched by its place on the command line. add_argument("--dataset") defines an optional argument: matched by name, and when absent it takes its default. Both land on the Namespace.

open as a page

What is the difference between os.environ["DB_URL"] and os.getenv("DB_URL", default)?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Subscripting os.environ raises KeyError when the variable is unset; os.getenv returns None, or the default you pass. Subscript settings the program cannot run without, so it fails loudly at startup, and use os.getenv only where a default is genuinely correct.

open as a page

What does subprocess.run() return, and how do you capture the child's output and fail on a non-zero exit?

level: juniorimportance: must knowfreq 76%
basics
~20 s

subprocess.run() blocks until the child exits and returns a CompletedProcess carrying args, returncode, stdout and stderr. Pass capture_output=True and text=True to get output as str, and check=True to raise CalledProcessError when the exit code is not zero.

open as a page

How should a Python CLI report failure — sys.exit codes, and sys.stderr versus sys.stdout?

level: middleimportance: must knowfreq 50%
basics
~20 s

Exit 0 for success and a small non-zero code for failure via sys.exit, which raises SystemExit. Send results a caller might pipe to sys.stdout, and diagnostics, warnings and errors to sys.stderr so they survive redirection.

open as a page

In subprocess.run, how is the args parameter interpreted with shell=True versus the default, and what does it cost?

level: middleimportance: must knowfreq 68%
basics
~20 s

With the default shell=False, args is a sequence and each element becomes exactly one argv entry, executed directly with no shell parsing. With shell=True on POSIX, args should be a single string handed to /bin/sh -c, so the shell re-parses it and metacharacters inside interpolated values take effect.

open as a page

Why use the logging module instead of print() in a Python application?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Every logging call carries a severity level, a logger name and a timestamp, and where it goes is decided once at startup rather than at the call site. print() writes an unconditional bare line to stdout with none of that.

open as a page

How do logging.handlers.RotatingFileHandler and TimedRotatingFileHandler differ?

level: juniorimportance: must knowfreq 50%
basics
~20 s

Both write to one file and roll it aside, but RotatingFileHandler rolls over when the file would exceed maxBytes, while TimedRotatingFileHandler rolls over on a clock boundary chosen by when and interval. Each keeps backupCount old files.

open as a page

Why call logging.getLogger(__name__) in each module instead of logging.info() directly?

level: juniorimportance: must knowfreq 62%
basics
~20 s

logging.getLogger(name) returns a logger named after the module's import path, so every record says where it came from and configuration can be aimed at one package. Calling logging.info goes through the root logger, which loses that origin.

open as a page

Why does a logging.Logger set to DEBUG still produce no DEBUG output?

level: middleimportance: must knowfreq 70%
basics
~20 s

Levels filter twice. The logger's own effective level decides whether a record is created at all, and then every handler applies its own level before emitting. A handler left at WARNING silences DEBUG no matter what the logger says.

open as a page

What does logging's extra= dict add to a LogRecord, and when does it raise KeyError?

level: middleimportance: must knowfreq 55%
basics
~20 s

Each key in the extra mapping becomes an attribute on the LogRecord itself, so a formatter can emit it as a field. Logger.makeRecord raises KeyError if a key collides with an existing record attribute or with message or asctime.

open as a page

Why does base64.b64encode reject a str, and what do you write instead?

level: juniorimportance: must knowfreq 60%
basics
~10 s

base64.b64encode is a bytes-to-bytes function: it needs a bytes-like object and returns bytes. Encode text first with str.encode('utf-8'), then call .decode('ascii') on the result to get a str for JSON.

open as a page

How do struct.pack and struct.unpack convert Python values to and from bytes?

level: juniorimportance: must knowfreq 40%
basics
~20 s

struct.pack takes a format string plus values and returns a bytes object laid out exactly as that format describes. struct.unpack reverses it and always returns a tuple, even when the format has a single field.

open as a page

How do Python's uuid.uuid4, uuid.uuid1 and uuid.uuid5 differ in where their bits come from?

level: juniorimportance: must knowfreq 62%
basics
~20 s

uuid.uuid4 fills 122 bits from the operating system's random source. uuid.uuid1 encodes a timestamp plus the host's 48-bit node address. uuid.uuid5 hashes a namespace UUID together with a name, so the same name always produces the same UUID.

open as a page

Why can zlib.compress exhaust memory on a multi-gigabyte file, and what replaces it?

level: middleimportance: must knowfreq 50%
basics
~10 s

zlib.compress takes one bytes object and returns another, so both the whole input and the whole output sit in memory at once. Stream instead: zlib.compressobj(), feed it chunks with compress(), and finish with flush().

open as a page

Why does struct.calcsize('@ci') exceed struct.calcsize('<ci')?

level: middleimportance: must knowfreq 34%
basics
~20 s

The '@' prefix means native byte order with native alignment, so struct inserts pad bytes before the int — typically eight bytes in total. The '<' prefix selects little-endian standard sizes with no alignment padding, giving exactly five.

open as a page

Which socket.socket calls set up a listening TCP server, and what does the client call?

level: juniorimportance: must knowfreq 52%
basics
~20 s

The server creates a socket, binds it to a local address, calls listen, then blocks in accept, which returns a new socket for one client; only that socket carries data. The client creates its own socket and calls connect.

open as a page

Why does selectors.EVENT_WRITE fire on nearly every loop pass, and when should you register for it?

level: middleimportance: must knowfreq 45%
basics
~20 s

A socket is writable whenever its kernel send buffer has room, which is almost always. Register selectors.EVENT_WRITE only while unsent bytes are actually queued for that socket; otherwise select() returns instantly every pass and the loop spins at full CPU.

open as a page

Why can socket.socket.recv return only part of the message the peer sent, and what fixes it?

level: middleimportance: must knowfreq 62%
basics
~20 s

TCP is a byte stream with no message boundaries, so recv returns whatever has arrived, up to the size you asked for. Frame messages yourself with a length prefix or a delimiter, and loop until one message is complete.

open as a page

What is the difference between urllib.error.HTTPError and urllib.error.URLError?

level: middleimportance: must knowfreq 55%
basics
~20 s

HTTPError means the server answered with a status urllib treats as an error; URLError means no HTTP answer arrived at all, such as a name-resolution or connection failure. HTTPError is a subclass of URLError, so catch it first.

open as a page

What does selectors.DefaultSelector let one thread do that a blocking socket.recv() cannot?

level: juniorimportance: should knowfreq 35%
basics
~20 s

It asks the kernel which of many registered sockets are ready right now, so one thread can serve thousands of connections. A blocking socket.recv() parks that thread on one connection until that single connection has data.

open as a page

In Python's DB-API, how do cursor fetchone(), fetchmany() and fetchall() differ?

level: juniorimportance: must knowfreq 62%
basics
~20 s

All three read from one cursor's open result set and advance the same position. fetchone() returns the next row or None when exhausted, fetchmany(n) returns up to n rows in a list, and fetchall() returns every remaining row.

open as a page

In Python's sqlite3, why pass values as ? placeholders instead of building the SQL with an f-string?

level: juniorimportance: must knowfreq 75%
basics
~20 s

sqlite3 compiles the statement once and binds each Python value as a typed parameter, so no quoting or escaping ever happens. An f-string splices the value into the statement text, where it can change what the SQL means.

open as a page

Why do a DB-API connection's uncommitted writes vanish when you close it?

level: middleimportance: must knowfreq 55%
basics
~20 s

PEP 249 connections are transactional by default and open a transaction implicitly, with no BEGIN call in the API. Only commit() makes the work durable; close() without it performs an implicit rollback, so the writes are discarded.

open as a page

What does Python's sqlite3 do about transactions by default, and how does the autocommit attribute change it?

level: middleimportance: must knowfreq 60%
basics
~20 s

By default sqlite3 opens a transaction implicitly before an INSERT, UPDATE, DELETE or REPLACE and leaves it open until you call Connection.commit; nothing else commits for you. Setting Connection.autocommit to True or False replaces that legacy behaviour with explicit modes.

open as a page

What does a DB-API driver's paramstyle attribute declare, and why does it hurt portability?

level: middleimportance: should knowfreq 38%
basics
~20 s

PEP 249 makes every driver module expose a paramstyle string naming the placeholder syntax it accepts: qmark, numeric, named, format or pyformat. Because the driver fixes the style, statements written for one driver do not run on another.

open as a page

Why should a decimal.Decimal be built from a string rather than from a float?

level: juniorimportance: must knowfreq 62%
basics
~10 s

Decimal(0.1) converts the float exactly, so it stores 0.1000000000000000055511151231257827..., the binary approximation the float already was. Decimal("0.1") parses the decimal digits you actually wrote and stores exactly one tenth.

open as a page

What does calling random.seed(42) do to the sequence returned by random.random()?

level: juniorimportance: must knowfreq 62%
basics
~20 s

It resets the internal state of the one Mersenne Twister generator that backs the random module's functions. Any run that seeds with the same value then replays the identical sequence of numbers in the same order.

open as a page

How does decimal.Decimal.quantize round a money amount, and what rounding does it use by default?

level: middleimportance: must knowfreq 48%
basics
~10 s

quantize takes a pattern Decimal such as Decimal("0.01") and returns a value with that same exponent, rounding the extra digits away. The rounding rule comes from the current decimal context, whose default is ROUND_HALF_EVEN.

open as a page

How do you choose between statistics.mean, median, stdev and pstdev in Python?

level: juniorimportance: should knowfreq 32%
basics
~20 s

statistics.mean averages every value, so one outlier drags it; statistics.median returns the middle value and ignores how extreme the tail is. statistics.stdev divides by n-1 for a sample, statistics.pstdev by n for a whole population.

open as a page

When does math.fsum give a different total than the built-in sum() over the same floats?

level: middleimportance: should knowfreq 32%
basics
~20 s

math.fsum tracks exact partial sums and rounds once at the end, so its total is always correctly rounded. The built-in sum() has compensated since Python 3.12, but its single correction term can still drift across widely separated magnitudes.

open as a page