Courseiva
Exceptions and File I/O →easyMultiple Choice

PCAP Exceptions and File I/O Practice Question

A programmer needs to write a function that reads a large binary file (over 1 GB) and returns its entire content as a bytes object. The function must handle the case where the path provided is actually a directory (IsADirectoryError) by returning an empty bytes object. Which implementation is most memory-efficient and correctly handles the directory case? Consider that reading the entire file into memory is acceptable for the business case.

⚠ Common exam trap

Python Institute often tests the distinction between catching a specific exception (`IsADirectoryError`) versus a broad parent class (`OSError`), and the misconception that a pre-check like `os.path.isfile()` is safer than exception handling, ignoring the TOCTOU race condition.

Answer choices

Why each option matters

Answer the question above first, then reveal the full breakdown to understand why each option is right or wrong.

Correct answer & explanation

✓

Use 'with open(path, 'rb') as f: return f.read()' inside a try-except IsADirectoryError catch that returns b''.

It uses a try-except block specifically catching `IsADirectoryError`, which is raised when `open()` is called on a directory path. The `with` statement ensures the file is properly closed, and `f.read()` returns the entire content as a bytes object, which is memory-efficient for this use case (the file is read in one large allocation, avoiding overhead from chunking).

Answer analysis

Option-by-option breakdown

For each option: why learners choose it and why it is or isn't the right answer here.

  • ✓

    Use 'with open(path, 'rb') as f: return f.read()' inside a try-except IsADirectoryError catch that returns b''.

    Why this is correct

    Opening with 'rb' returns a file object whose .read() method produces a single bytes object containing the entire file content. If the path points to a directory, calling .read() raises precisely IsADirectoryError (an OSError subclass on POSIX), and the narrowly-scoped except IsADirectoryError catches only that case, returning b''. The with block guarantees the file object is closed even if the read fails, and no other OS errors (such as PermissionError) are swallowed.

  • ✗

    Use 'with open(path, 'rb') as f: return f.read()' inside a try-except OSError that returns b''.

    Why it's wrong here

    Using except OSError is far too broad: IsADirectoryError is only one of many OSError subclasses, so this handler also catches PermissionError, FileNotFoundError, FileExistsError, and other operational failures. As a result, a permission problem or a missing file would silently produce an empty bytes object instead of propagating an exception, hiding real errors from the caller. The whole point of catching IsADirectoryError specifically is to treat only the directory case specially and let all other OS errors surface normally.

  • ✗

    Use os.path.isfile(path) to check before opening; if not a file, return b''.

    Why it's wrong here

    This approach suffers from a time-of-check-to-time-of-use (TOCTOU) race: between the os.path.isfile(path) check and the subsequent open(path, 'rb'), the filesystem state may change (for example, the file can be deleted or replaced by a directory), so the check does not guarantee the open-and-read will succeed. It also uses an LBYL (look-before-you-leap) style rather than Python's idiomatic EAFP (easier to ask forgiveness than permission), and if path is a directory the function must still handle opening and reading it, since isfile only informs later code. A pre-check cannot replace the need for a robust try/except around the actual open/read operation.

  • ✗

    Use 'with open(path, 'rb') as f: return [chunk for chunk in iter(lambda: f.read(1024), b'')]' inside a try-except IsADirectoryError.

    Why it's wrong here

    Although this option correctly catches IsADirectoryError, the list comprehension grows a list of 1024-byte bytes chunks, and the function returns that list rather than a single bytes object. For code that expects the full binary content as one bytes value—such as when writing to a socket or hashing—a list is the wrong type; at best it would require b''.join(...) to concatenate the chunks. Additionally, constructing a list of chunks consumes more memory than a single .read() due to per-chunk object overhead, and it only delays, rather than solves, the directory error because the first f.read(1024) on a directory still raises IsADirectoryError.

About these practice questions

This PCAP question is part of Courseiva's 421-question bank — original exam-style content with full explanations and wrong-answer analysis, never real exam questions or exam dumps. Learn why practice questions differ from exam dumps →

How Courseiva writes practice questions · Editorial policy

JA

Written by Johnson Ajibi, MSc IT Security

Senior Network & Security Engineer · founder of Courseiva

This PCAP practice question is part of Courseiva's free Python Institute certification practice question bank. Courseiva provides original exam-style practice questions with explanations, topic-based practice, mock exams, readiness tracking, and study analytics to help learners prepare for the PCAP exam.