Courseiva

CCNA Exceptions and File I/O Questions

75 of 76 questions · Page 1/2 · Exceptions and File I/O · Answers revealed

1
MCQeasy

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.

A.Use 'with open(path, 'rb') as f: return f.read()' inside a try-except IsADirectoryError catch that returns b''.
B.Use 'with open(path, 'rb') as f: return f.read()' inside a try-except OSError that returns b''.
C.Use os.path.isfile(path) to check before opening; if not a file, return b''.
D.Use 'with open(path, 'rb') as f: return [chunk for chunk in iter(lambda: f.read(1024), b'')]' inside a try-except IsADirectoryError.
AnswerA

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.

Why this answer

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).

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.

How to eliminate wrong answers

Option B is wrong because catching `OSError` is too broad; it would suppress legitimate errors like permission denied or disk full, masking bugs. Option C is wrong because `os.path.isfile()` introduces a race condition (TOCTOU) — the file could be replaced by a directory between the check and the open, and it does not handle the case where the path is a directory that is later opened. Option D is wrong because it reads the file in 1024-byte chunks and collects them into a list, which is less memory-efficient than a single `f.read()` (the list overhead and multiple allocations waste memory), and it still catches `IsADirectoryError` correctly but is not the most memory-efficient.

2
MCQeasy

Which method of a file object reads the entire content of a text file as a single string?

A.readall()
B.read()
C.readline()
D.readlines()
AnswerB

The read() method, called with no arguments, reads from the current file position to EOF and returns the entire remaining content as a single string in text mode, or a single bytes object in binary mode. It is the only method among the options that returns the whole file content as one undivided value, which is exactly what the question asks for.

Why this answer

The `read()` method, when called without arguments or with a negative size, reads the entire contents of a file as a single string. This is the standard Python file object method for reading all text at once, returning a str object. It is the correct choice because the question explicitly asks for a method that returns the entire content as a single string.

Exam trap

Python Institute often tests the distinction between `read()` (returns a single string) and `readlines()` (returns a list of strings), causing candidates to confuse the two methods when the question specifies 'as a single string'.

How to eliminate wrong answers

Option A is wrong because `readall()` is not a valid method of a Python file object; it does not exist in the standard file I/O API. Option C is wrong because `readline()` reads only the next line from the file, returning a single string that ends with a newline character, not the entire content. Option D is wrong because `readlines()` reads all lines and returns them as a list of strings, each representing one line, not as a single concatenated string.

3
MCQmedium

A company runs a data processing pipeline that reads CSV files from a network drive. Occasionally, the network drive is unreachable causing FileNotFoundError. The current code uses a bare except clause that catches all exceptions, which also masks programming errors like NameError. The lead developer wants to implement a more robust exception handling strategy. The requirement is to log the specific error (including the filename) and retry the operation up to 3 times with a 2-second delay between retries. If after 3 attempts the file is still inaccessible, the pipeline should skip the file and continue with the next one. Which approach best meets these requirements?

A.Use os.path.exists before opening the file, and if it returns False, log and skip.
B.Use a try-except block catching OSError, with a retry loop that logs the error and continues after max retries.
C.Use a try-except block catching Exception, with a retry loop and logging.
D.Use a with statement; if an exception occurs, call the function recursively up to 3 times.
AnswerB

This is the correct strategy because it follows the easier-to-ask-forgiveness-than-permission (EAFP) idiom and catches OSError exactly, which is the base class for I/O failures such as FileNotFoundError, PermissionError, and BrokenPipeError. The retry loop with a maximum retry count is essential for transient network-drive hiccups or brief file locks, while logging the specific error and the retry attempt gives operators visibility into what happened. After exhausting the retries, the loop logs the final failure and continues to the next file, ensuring the pipeline does not crash on a single bad input. This approach is precise, non-recursive, and aligns with best practices for robust file processing.

Why this answer

It catches OSError, which is the parent class for file-related errors like FileNotFoundError, while still allowing programming errors like NameError to propagate. The retry loop with a 2-second delay and a maximum of 3 attempts satisfies the requirement, and after exhausting retries, the loop naturally continues to the next file, skipping the problematic one.

Exam trap

Python Institute often tests the distinction between catching OSError (specific to file/OS errors) versus Exception (which catches everything including NameError), and candidates mistakenly choose the broader catch because they think 'all exceptions' includes file errors, ignoring the requirement to not mask programming errors.

How to eliminate wrong answers

Option A is wrong because using os.path.exists before opening introduces a TOCTOU (time-of-check-time-of-use) race condition; the file could be deleted or become unavailable between the check and the open call, and it does not handle other OSError subtypes like PermissionError. Option C is wrong because catching Exception is too broad and will mask programming errors such as NameError or TypeError, which violates the requirement to avoid masking such errors. Option D is wrong because recursive calls risk hitting Python's recursion limit (default 1000) and do not provide a clean retry loop with delay; also, the with statement does not inherently handle retries or logging.

4
MCQmedium

A developer needs to write a function that safely divides two numbers and returns None if division by zero occurs. Which implementation is most Pythonic?

A.def safe_divide(a, b): try: return a/b except ZeroDivisionError: return None
B.def safe_divide(a, b): return a/b if b else None
C.def safe_divide(a, b): if b != 0: return a/b else: return None
D.def safe_divide(a, b): try: return a/b except ValueError: return None
AnswerA

This is the canonical EAFP implementation: it attempts the division inside a try block and catches only the exact exception that signals division by zero. ZeroDivisionError is a subclass of ArithmeticError and is raised whenever a numeric denominator evaluates to zero, so returning None is a clean and specific fallback. Any other exception (such as TypeError for incompatible operands) is deliberately allowed to propagate, preserving the caller's ability to debug the real error.

Why this answer

It uses a try-except block to catch the specific ZeroDivisionError that Python raises when dividing by zero. This is the most Pythonic approach, following the EAFP (Easier to Ask for Forgiveness than Permission) principle, which is preferred over LBYL (Look Before You Leap) in Python. The function returns None only when the exception occurs, preserving the natural behavior of division for all other cases.

Exam trap

Python Institute often tests the distinction between EAFP and LBYL, and the trap here is that candidates may choose Option C (LBYL) because it appears safer, or Option D because they confuse ValueError with ZeroDivisionError, not realizing that Python raises a specific exception for division by zero.

How to eliminate wrong answers

Option B is wrong because it uses a conditional expression that evaluates b as a truthy value, which fails for non-numeric zero-like values (e.g., 0.0, 0j) and does not handle cases where b is a non-zero value that causes a different exception (e.g., string division). Option C is wrong because it implements LBYL (Look Before You Leap) by checking b != 0 before dividing, which is less Pythonic than EAFP and duplicates the check that the exception mechanism handles more cleanly. Option D is wrong because it catches ValueError, which is not raised by division by zero; the correct exception is ZeroDivisionError, so this implementation would let the ZeroDivisionError propagate unhandled.

5
Multi-Selectmedium

Which TWO statements about exception handling in Python are correct? (Select exactly 2.)

Select 2 answers
A.A single except clause can catch multiple exception types by passing a tuple of exceptions.
B.The order of except clauses does not matter because only one will match.
C.The finally block always executes, even if the try block contains a return statement.
D.An else block can be used without any except blocks in a try statement.
E.The else block in a try statement executes only if an exception was raised.
AnswersA, C

A single except clause can catch multiple exception types by passing a tuple, e.g., `except (ValueError, TypeError) as e:`. The raised exception is matched against the tuple using `isinstance()`, so any exception that is an instance of one of the listed types (including subclasses) is handled. Parentheses are mandatory because the syntax requires a literal tuple; writing `except ValueError, TypeError:` is invalid in Python 3. This lets you group unrelated exceptions that need identical handling into one clause.

Why this answer

Python's except clause accepts a tuple of exception types, allowing a single handler to catch multiple exception types. For example, `except (ValueError, TypeError):` will catch either exception, which is a concise way to handle related errors without duplicating code.

Exam trap

Python Institute often tests the misconception that the else block runs after an exception or that except order is irrelevant, leading candidates to select B or E instead of recognizing the correct behavior of tuple-based except clauses and the unconditional execution of finally.

6
Matchingmedium

Match each Python data structure to its mutability.

Drag a concept onto its matching description — or click a concept then click the description.

Concepts
Matches

Mutable

Immutable

Mutable

Immutable

Mutable

Why these pairings

In Python, list, dict, and set are mutable data structures, meaning their contents can be modified. Tuple, string, and frozenset are immutable; their contents cannot be changed after creation. Common confusions include thinking tuples are mutable (they are not) or that frozensets are mutable (they are not).

7
MCQhard

What is the output of the following code? try: exec('1/0') except: print('error') else: print('no error') finally: print('done')

A.error done
B.done error
C.error
D.done
AnswerA

`exec('1/0')` raises a `ZeroDivisionError`, caught by the bare `except`, so `error` prints. The `else` block runs only when no exception occurs, so `no error` is skipped. The `finally` block always executes, printing `done`. Output is therefore `error done`.

Why this answer

The `exec('1/0')` raises a `ZeroDivisionError`, which is caught by the bare `except:` clause, printing 'error'. The `else` clause is skipped because an exception occurred, but the `finally` clause always executes, printing 'done'. Thus the output is 'error' followed by 'done'.

Exam trap

Python Institute often tests the order of execution in exception handling, specifically that `finally` always runs after `except` (not before), and that `else` is skipped when an exception occurs, causing candidates to misorder the output or forget the `finally` block.

How to eliminate wrong answers

Option B is wrong because it suggests 'done' prints before 'error', but the `except` block runs before the `finally` block, so the order is 'error' then 'done'. Option C is wrong because it omits the `finally` block output entirely, but `finally` always executes regardless of exceptions. Option D is wrong because it omits the 'error' output, but the exception is caught and 'error' is printed.

8
MCQeasy

A developer opens a CSV file with open('data.csv', 'r', encoding='utf-8') and reads it with readline(). The first line contains a non-ASCII character that the file declares as UTF-8. Which exception is most likely raised if the file actually contains bytes that are not valid UTF-8?

A.UnicodeDecodeError
B.ValueError
C.SyntaxError
D.UnicodeEncodeError
AnswerA

When a file is opened in text mode with an explicit encoding, reading bytes that do not form valid sequences for that encoding raises UnicodeDecodeError, a subclass of UnicodeError. In this scenario the declared encoding is UTF-8, so invalid UTF-8 byte sequences trigger this exception during readline(). Handling it allows the program to log the offending position or fall back to a different decoding strategy.

Why this answer

Reading text from a file opened with a declared encoding performs decoding, so invalid byte sequences raise UnicodeDecodeError. The other exceptions describe unrelated conditions: encoding errors happen on write, syntax errors happen at parse time, and ValueError is a generic mismatch. Handling the decode error lets the program recover from malformed data.

Exam trap

The trap here is mixing up UnicodeDecodeError and UnicodeEncodeError, which apply to opposite directions of text conversion.

9
MCQmedium

A developer has a function that performs several operations and may raise different exceptions. The developer wants to catch a specific exception and then re-raise it after logging. Which code snippet correctly re-raises the same exception without losing its traceback?

A.except ValueError as e: log.error(e); raise
B.except ValueError as e: log.error(e); return None
C.except ValueError as e: log.error(e); raise ValueError('New')
D.except ValueError as e: log.error(e); pass
AnswerA

The bare `raise` inside the `except` block re-raises the identical exception object that was caught, preserving its full traceback, original message, and any associated attributes. Logging first allows the current layer to record the failure, then the same exception continues propagating up the call stack for the caller to handle. This is the canonical way to log-and-rethrow without altering the exception's identity or stack trace, making the failure visible at every layer that observes it.

Why this answer

Using a bare `raise` statement inside an `except` block re-raises the original exception instance, preserving its full traceback. This is the standard Python idiom for logging an exception and then propagating it unchanged, ensuring that the original call stack and error context are not lost.

Exam trap

Python Institute often tests the distinction between a bare `raise` (which preserves the original exception and traceback) and `raise SomeException(...)` (which creates a new exception and loses the original context), leading candidates to incorrectly choose the latter when they think they need to 're-raise' by specifying the exception class again.

How to eliminate wrong answers

Option B is wrong because `return None` does not re-raise the exception; it silently swallows the error and returns `None`, which changes the function's behavior and loses the exception entirely. Option C is wrong because `raise ValueError('New')` creates a brand-new exception instance, discarding the original exception's traceback and potentially its type or message, which breaks the requirement to re-raise the same exception. Option D is wrong because `pass` does nothing, causing the exception to be caught and then ignored (the `except` block ends without re-raising), effectively suppressing the error.

10
MCQhard

A developer writes a helper that copies lines from one text file to another. The helper opens both files with open() inside a try block and closes them in a finally block. If an exception occurs while writing, which statement about the finally block is correct?

A.The finally block runs only if the exception is caught by an except clause in the same try statement.
B.The finally block is skipped when an exception occurs, so the files remain open.
C.The finally block runs after the exception has propagated to the caller, so closing there is too late.
D.The finally block runs before the exception propagates, so both files can be closed there.
AnswerD

A finally block executes as the try statement unwinds, whether the try block completed normally or raised. In this scenario, when the write fails, control transfers to finally before the exception continues to the caller, so both file handles can be closed there. This guarantees cleanup without suppressing the original exception, which is the intended behavior.

Why this answer

A finally clause executes during the unwinding of its try statement, before the exception propagates to the caller. That makes it the right place to close both files when the write fails, ensuring cleanup without catching or suppressing the error. The other statements misdescribe when finally runs relative to exception handling and propagation.

Exam trap

The trap here is thinking that finally is conditional on an except clause catching the exception, when finally runs unconditionally during unwinding.

11
Multi-Selecthard

Which THREE of the following exception types are subclasses of OSError in Python 3?

Select 3 answers
A.FileNotFoundError
B.IOError
C.UnicodeError
D.PermissionError
E.EOFError
AnswersA, B, D

FileNotFoundError is a concrete subclass of OSError, raised when a required file or directory does not exist. Because it inherits from OSError, it is caught by an except OSError handler, yet it is distinct from PermissionError, which occurs when the item exists but access is denied. This makes it one of the three options in the OSError hierarchy.

Why this answer

FileNotFoundError is a direct subclass of OSError, raised when a file or directory is requested but does not exist at the given path. This is part of Python's exception hierarchy for operating system-related errors, specifically for file operations that fail due to missing resources.

Exam trap

Python Institute often tests the misconception that IOError is a separate exception type in Python 3, when in fact it is an alias for OSError, and that UnicodeError or EOFError belong to the OSError family, which they do not.

12
Multi-Selectmedium

A developer is writing a function that reads a configuration file. The function must distinguish between a missing file, a permission problem, and a malformed file, and it must not leave the file open on any path. Which TWO techniques are appropriate for this requirement? (Choose two.)

Select 2 answers
A.Catch Exception in a single handler and inspect the message text to decide which error occurred.
B.Open the file without a with statement and call close() only after the parsing code completes successfully.
C.Catch FileNotFoundError and PermissionError in separate except clauses to produce distinct error messages.
D.Use a with open(...) as f: block so the file is closed whether the body succeeds or raises.
E.Rely on the garbage collector to close the file when the function returns, and raise a custom exception for all failures.
AnswersC, D

FileNotFoundError and PermissionError are distinct subclasses of OSError, so separate except clauses allow the function to report a missing file differently from a permission problem. This satisfies the requirement to distinguish those two cases. A malformed file would still need separate handling, such as catching a parsing exception, but these two clauses cover the file-access distinctions the scenario calls out.

Why this answer

Using with open(...) guarantees the file is closed on every exit path, and catching FileNotFoundError and PermissionError separately lets the function report distinct causes. The broad Exception handler hides bugs and relies on message text, the success-only close leaks the file on errors, and relying on the garbage collector is non-deterministic. Together, the context manager and specific handlers meet the stated requirements.

Exam trap

The trap here is believing that CPython's reference counting makes explicit close() unnecessary, when deterministic cleanup should use with or finally.

13
MCQmedium

Refer to the exhibit. A developer is writing a script to read this JSON configuration file. The script should write the logging configuration to a separate file called 'logging.conf'. Which file mode should be used to create the file if it doesn't exist, and overwrite it if it does?

A.'x'
B.'r+'
C.'a'
D.'w'
AnswerD

Mode 'w' opens the file for writing, creating the file if it does not exist and truncating it to zero length if it does, thereby discarding all previous contents. This exactly matches the need to write a complete, fresh set of data: any existing content is erased before the first write, ensuring that the final file contains only the current output with no stale data.

Why this answer

('w') is correct because the 'w' mode opens a file for writing, truncating it first if it exists, and creating it if it does not. This matches the requirement to overwrite an existing 'logging.conf' file or create a new one if absent.

Exam trap

Python Institute often tests the distinction between 'w' and 'x' modes, where candidates mistakenly choose 'x' thinking it creates a new file, forgetting that 'x' raises an error if the file already exists, thus failing the overwrite requirement.

How to eliminate wrong answers

Option A ('x') is wrong because 'x' is an exclusive creation mode that raises a FileExistsError if the file already exists, so it cannot overwrite an existing file. Option B ('r+') is wrong because 'r+' opens a file for reading and writing but does not create the file if it does not exist; it raises a FileNotFoundError. Option C ('a') is wrong because 'a' opens a file for appending, which does not overwrite existing content; it writes new data at the end of the file.

14
MCQmedium

What will be printed?

A.-1
B.0
C.An exception is raised.
D.None
AnswerD

The correct output is None because `int("abc")` raises a ValueError, which is caught by the matching `except ValueError` block. That handler assigns the result variable to None, and when the code later prints that variable, Python displays the string representation of None (i.e., "None").

Why this answer

None. This question likely tests that Python functions return None by default when no explicit return statement is present, and printing that value yields None. Therefore, option D is correct.

Exam trap

Candidates often mistake the absence of a return statement for an implicit return of 0 or -1, or think an exception is raised. However, Python functions default to returning None, and printing that yields 'None'.

How to eliminate wrong answers

Option A is wrong because -1 is never printed; the code does not contain any print statement that would output -1, and the exception prevents any output. Option B is wrong because 0 is never printed; the code does not contain any print statement that would output 0, and the exception prevents any output. Option C is wrong because while an exception is raised, the question asks 'What will be printed?' and the answer is that nothing is printed (None), not that an exception is raised as the printed output.

15
MCQeasy

Which of the following statements about the `finally` block is true?

A.It executes only if no exception is raised.
B.It does not execute if a return statement is in try block.
C.It executes only if an exception is raised.
D.It always executes, regardless of exceptions.
AnswerD

The `finally` block guarantees execution after the `try` block completes, whether an exception is raised, caught, or the block exits via `return`, `break` or `continue`. This satisfies the stem's requirement for a statement that is always true, since only `finally` provides unconditional cleanup semantics in Python.

Why this answer

The `finally` block in Python is designed to always execute after the `try` and `except` blocks, regardless of whether an exception was raised or not. This includes cases where a `return`, `break`, or `continue` statement is executed in the `try` block, or even if an unhandled exception occurs. The `finally` block is guaranteed to run before the function returns or the exception propagates, ensuring cleanup actions like closing files or releasing resources.

Exam trap

Python Institute often tests the misconception that a `return` statement in the `try` block prevents the `finally` block from executing, but in Python, the `finally` block always runs before the function returns, making this a common trap for candidates who confuse Python's behavior with that of other languages.

How to eliminate wrong answers

Option A is wrong because the `finally` block executes regardless of whether an exception is raised, not only when no exception occurs. Option B is wrong because the `finally` block does execute even if a `return` statement is in the `try` block; the `finally` block runs before the function actually returns. Option C is wrong because the `finally` block executes regardless of whether an exception is raised, not only when an exception occurs.

16
MCQmedium

A Python script that processes log files uses the following code: with open('log.txt', 'r') as f: lines = f.readlines() for line in lines: # process What is a potential inefficiency in this code?

A.The file is not properly closed after processing.
B.Reading the entire file into memory may be wasteful for large files.
C.Using readlines() is the most efficient way to iterate over lines.
D.The file should be opened in binary mode for better performance.
AnswerB

This is the correct statement. Calling `readlines()` reads every line of the file into a list of strings, meaning the entire file content is loaded into memory at once. For large log files, this can consume a massive amount of RAM, potentially causing the program to slow down or crash with a MemoryError. A more memory-efficient approach is to iterate directly over the file object (`for line in f:`), which reads one line at a time lazily, keeping the memory footprint low regardless of file size.

Why this answer

`readlines()` loads the entire file into memory as a list of strings. For large log files, this can consume significant memory and cause performance degradation or even memory errors. A more memory-efficient approach is to iterate directly over the file object (e.g., `for line in f:`), which reads one line at a time from disk.

Exam trap

Python Institute often tests the misconception that `readlines()` is the standard or recommended way to read a file line by line, when in fact the file object itself is an iterator that should be used for large files to avoid memory bloat.

How to eliminate wrong answers

Option A is wrong because the `with` statement ensures the file is automatically closed when the block exits, even if an exception occurs. Option C is wrong because `readlines()` is not the most efficient way to iterate over lines; it reads all lines into memory at once, whereas iterating over the file object directly is more memory-efficient. Option D is wrong because opening in binary mode (`'rb'`) would not improve performance for text log processing and would require manual decoding of bytes to strings, adding complexity without benefit.

17
MCQeasy

A junior developer is writing a helper that reads a small log file and returns its contents as a single string. The file is guaranteed to exist and be readable. The helper currently uses an explicit open, a try/finally block, and manual close call. A reviewer asks for the most idiomatic Python 3 replacement that guarantees closure. Which construct should be used?

A.f = open('app.log'); data = f.read(); f.close(); return data
B.with open('app.log') as f: return f.read()
C.data = open('app.log').read(); return data
D.f = open('app.log'); try: return f.read(); finally: pass
AnswerB

The with statement is a context manager that calls close on the file object when the block exits, whether normally or through an exception. It replaces the manual try/finally and close calls with a single readable construct. This is the idiomatic Python 3 approach and directly satisfies the reviewer's request for guaranteed closure.

Why this answer

The with statement uses the context manager protocol, invoking __exit__ on the file object so close runs even when an exception propagates out of the block. That makes it the idiomatic replacement for manual try/finally plus close. The alternatives either skip cleanup on exceptions, depend on garbage collection, or contain an empty finally that releases nothing.

Exam trap

The trap here is treating a plain open followed by a close as equivalent to the with statement, forgetting that an exception between them bypasses the close call entirely.

18
MCQhard

A senior developer in a team argues that using try-except blocks is slower than checking conditions with if statements. They propose replacing all try blocks that handle file I/O errors with existence checks using os.path.exists before opening files. During a code review, you recall that Python's official documentation and best practices prefer EAFP (Easier to Ask for Forgiveness than Permission) over LBYL (Look Before You Leap) in many cases, especially in concurrent environments. The team's application is a multi-threaded web server that serves static files from a shared directory. Which is the strongest counterargument against the senior developer's proposal?

A.if statements are harder to read and maintain.
B.try-except can catch multiple exception types more cleanly.
C.try-except blocks have no performance cost at all.
D.LBYL leads to race conditions in concurrent code because the file's state can change between the check and the use.
AnswerD

This is the classic time-of-check-to-time-of-use (TOCTOU) race: in a multithreaded server, two threads can evaluate `os.path.exists(path)` at nearly the same instant, and then one thread may delete or replace the file before the other actually opens it. The check and the use are not atomic, so LBYL gives a false sense of safety. EAFP, by contrast, wraps the open itself in a try-except, handling the failure exactly when it occurs and eliminating the gap.

Why this answer

In a multi-threaded web server, the LBYL approach (checking with os.path.exists) introduces a classic TOCTOU (Time of Check, Time of Use) race condition: between the existence check and the actual file open, another thread could delete or rename the file, causing the open to fail despite the check passing. Python's EAFP idiom (try-except) avoids this window by attempting the operation directly and handling the exception if it fails, which is inherently atomic with respect to the file system state. This is why official Python documentation recommends EAFP over LBYL in concurrent environments.

Exam trap

Python Institute often tests the misconception that try-except is purely about style or performance, when in reality the critical exam point is that LBYL introduces race conditions in concurrent code, making EAFP the safer and recommended pattern.

How to eliminate wrong answers

Option A is wrong because readability is subjective and not the strongest technical counterargument; if statements can be written clearly, and the core issue is correctness, not style. Option B is wrong because while try-except can catch multiple exception types cleanly, this is a convenience feature and does not address the fundamental race condition problem in concurrent file access. Option C is wrong because try-except blocks do have a small performance cost when an exception is raised (though negligible in I/O-bound code), but the claim that they have 'no performance cost at all' is factually incorrect and misses the point that the primary concern is correctness, not micro-optimization.

19
MCQmedium

Refer to the exhibit. Which of the following Python code snippets would generate this error?

A.int('abc')
B.str(123)
C.print('abc')
D.float('abc')
AnswerA

int('abc') invokes Python's integer constructor on the non-numeric string 'abc'. Since the string does not contain a valid integer literal—even after stripping surrounding whitespace or handling an optional sign—the conversion fails, raising a ValueError with the exact message "invalid literal for int() with base 10: 'abc'". This is the precise exception and message that the exhibit/question targets, making this the correct snippet.

Why this answer

`int('abc')` attempts to convert the string `'abc'` to an integer, which is not a valid numeric literal. Python raises a `ValueError` with the message 'invalid literal for int() with base 10: 'abc''. This error occurs because the `int()` function expects a string that represents a valid integer in the specified base (default base 10), and 'abc' does not meet that criterion.

Exam trap

Python Institute often tests the exact wording of Python error messages, so the trap here is that candidates may confuse `ValueError` from `int()` with `ValueError` from `float()`, but the error message in the exhibit specifically cites 'invalid literal for int()', making only `int('abc')` the correct match.

How to eliminate wrong answers

Option B is wrong because `str(123)` successfully converts the integer 123 to the string '123', which is a valid operation and does not raise any error. Option C is wrong because `print('abc')` simply prints the string 'abc' to the standard output; it does not involve any type conversion that could raise a ValueError. Option D is wrong because `float('abc')` would also raise a ValueError, but the error message would be 'could not convert string to float: 'abc'', which is different from the specific error shown in the exhibit (which mentions 'invalid literal for int()').

The exhibit's error message explicitly references `int()` and base 10, so only `int('abc')` matches.

20
Multi-Selecteasy

Which TWO of the following are correct statements about the 'with' statement in Python file I/O?

Select 2 answers
A.It ensures the file is closed when the block exits.
B.It can only be used with file objects.
C.It automatically opens the file without needing open().
D.It ensures that resources are released even if an exception is raised.
E.It prevents any exception from occurring during file operations.
AnswersA, D

The `with` statement invokes the context manager's `__exit__` method on block exit, and for file objects that method calls `close()`. This makes file closure deterministic and automatic, even if the block ends early due to a `return`, `break`, or `continue`. A bare `open()` without `try/finally` would not provide this guarantee.

Why this answer

The 'with' statement in Python acts as a context manager that automatically calls the file object's __exit__ method when the block exits, which in turn invokes the file's close() method. This guarantees that the file is properly closed, even if an exception occurs within the block, ensuring deterministic resource cleanup.

Exam trap

Python Institute often tests the misconception that the 'with' statement is exclusive to file objects or that it automatically opens files, when in fact it is a general-purpose context manager that requires an already-opened resource and does not suppress exceptions.

21
MCQeasy

A developer writes a script to read a configuration file that may not exist. The script should handle the error gracefully and continue. Which approach is most Pythonic?

A.Use a try-except block catching FileNotFoundError
B.Use a try-except block catching OSError
C.Use os.path.exists to check, then open if it exists
D.Use an if statement to check file size
AnswerA

Catching FileNotFoundError explicitly handles the missing-file condition while allowing execution to continue, which is the idiomatic Python approach. It satisfies the graceful-continuation constraint precisely, unlike broad exception handling or pre-checking with os.path.exists, which introduces race conditions.

Why this answer

It directly catches the specific `FileNotFoundError` exception, which is a subclass of `OSError` and is raised when a file does not exist. This approach follows the Pythonic principle of EAFP (Easier to Ask for Forgiveness than Permission), allowing the script to attempt the operation and handle the failure gracefully without redundant checks.

Exam trap

Python Institute often tests the distinction between catching a specific exception (`FileNotFoundError`) versus a broader parent exception (`OSError`), and the trap here is that candidates may choose the broader catch thinking it is safer, without realizing it can mask other critical errors.

How to eliminate wrong answers

Option B is wrong because catching `OSError` is too broad; it would also catch other operating system errors (e.g., permission denied, disk full) that may require different handling, masking the specific file-not-found scenario. Option C is wrong because using `os.path.exists` introduces a race condition (TOCTOU — Time of Check to Time of Use) where the file could be deleted or created between the check and the open call, and it violates the Pythonic EAFP idiom by using LBYL (Look Before You Leap). Option D is wrong because checking file size does not determine if a file exists; a file with zero size exists, and a non-existent file has no size to check, making this approach logically incorrect and unreliable.

22
Matchingmedium

Match each Python module to its purpose.

Drag a concept onto its matching description — or click a concept then click the description.

Concepts
Matches

Mathematical functions

Generate pseudo-random numbers

Manipulate dates and times

Work with JSON data

Interact with operating system

Why these pairings

Common Python standard library modules: os (operating system interface), sys (interpreter access), json (JSON handling), datetime (date and time), re (regular expressions), math (mathematical functions).

23
MCQhard

Consider the code fragment: f = open('data.txt', 'r') data = f.read() process_data(data) f.close() What is the primary risk if an exception occurs during process_data(data)?

A.The file descriptor may be leaked because the close() call is skipped.
B.The exception will be silently suppressed.
C.The file will be automatically closed by Python's garbage collector immediately.
D.The file contents will be corrupted.
AnswerA

An exception inside `process_data(data)` unwinds the stack before `f.close()` executes, leaving the file descriptor open until garbage collection reclaims it. That satisfies the stem's leak constraint: `close()` is skipped, so the descriptor is not released deterministically. A `with` statement or `try/finally` guarantees closure.

Why this answer

If `process_data(data)` raises an exception, the `f.close()` statement is never executed, leaving the file descriptor open. This is a resource leak that can exhaust system file handles, especially in long-running applications. Python's `with` statement is the recommended approach to guarantee automatic cleanup even when exceptions occur.

Exam trap

Python Institute often tests the misconception that Python's garbage collector immediately closes files, when in reality it only closes them during an unpredictable collection cycle, making explicit cleanup essential.

How to eliminate wrong answers

Option B is wrong because exceptions are not silently suppressed; they propagate up the call stack unless caught by an explicit `try-except` block. Option C is wrong because Python's garbage collector does not immediately close file descriptors; it may close them at an indeterminate time, and relying on it is poor practice and can lead to resource exhaustion. Option D is wrong because an exception during `process_data(data)` does not corrupt the file contents on disk; the file was opened in read mode, and the data is already read into memory before the exception occurs.

24
Multi-Selectmedium

Which TWO of the following are true about the 'with' statement in Python file I/O?

Select 2 answers
A.It can only be used with file objects
B.It is equivalent to a try/finally block
C.It automatically closes the file after the block
D.It does not require an __exit__ method
E.It requires the object to have an __enter__ method only
AnswersB, C

The with statement is semantically equivalent to a try/finally block because the interpreter guarantees that __exit__ is invoked when the block ends, whether it finishes normally or an exception is raised. This ensures cleanup code always runs, just as finally does after try. The key difference is that with also calls __enter__ at the start to initialize the resource, making it a structured way to pair setup and teardown.

Why this answer

The 'with' statement in Python is designed to simplify exception handling by encapsulating the setup and teardown of a resource in a context manager, which is functionally equivalent to a try/finally block. When you use 'with', the context manager's __exit__ method is guaranteed to be called even if an exception occurs, ensuring that cleanup actions like closing a file are performed, just as a finally clause would.

Exam trap

Python Institute often tests the misconception that the 'with' statement is only for file I/O, but the trap here is that candidates forget the context manager protocol requires both __enter__ and __exit__ methods, not just one, and that it applies to any object implementing that protocol.

25
MCQeasy

In Python, if you have a try block followed by an except clause that catches all exceptions, which of the following is true about the else clause?

A.The else clause runs only if no exception is raised in the try block.
B.The else clause runs only if an exception occurs.
C.The else clause runs before the finally block regardless of exceptions.
D.The else clause is used to specify additional exception handlers.
AnswerA

The else clause is part of a try/except/else/finally compound statement. It executes only when the try block completes without raising any exception, meaning control flows to else immediately after the last statement in try. If an exception occurs, else is skipped and control jumps to a matching except handler instead. This makes else ideal for code that should run only on success, such as logging successful completion or proceeding with a computed result.

Why this answer

In Python, the `else` clause in a `try` statement executes only if no exception was raised in the `try` block. This is true regardless of whether the `except` clause catches all exceptions (e.g., bare `except:` or `except Exception:`). The `else` block is specifically designed for code that should run only when the `try` block completes successfully without any exception.

Exam trap

The trap here is that candidates often confuse the `else` clause with a second chance to handle exceptions or think it runs unconditionally before `finally`, when in fact it is strictly tied to the successful execution of the `try` block and is skipped entirely if any exception occurs.

How to eliminate wrong answers

Option B is wrong because the `else` clause runs only when no exception occurs, not when an exception occurs; code that runs on an exception belongs in the `except` block. Option C is wrong because the `else` clause runs before the `finally` block only if no exception was raised, but if an exception is raised, the `else` block is skipped entirely and the `finally` block still runs; the order is not guaranteed to be `else` before `finally` in all cases. Option D is wrong because the `else` clause is not used to specify additional exception handlers; additional exception handlers are specified by additional `except` clauses, while the `else` clause is for code that executes only on successful completion of the `try` block.

26
MCQhard

Refer to the exhibit. If both data.txt and backup.txt do not exist, what is the output?

A.Prints contents of backup.txt
B.Nothing
C.FileNotFoundError
D.'No file found'
AnswerD

Because neither data.txt nor backup.txt exists, the outer try raises FileNotFoundError, and then the inner try also raises FileNotFoundError. The inner except FileNotFoundError block catches this second exception and executes print('No file found'), making that literal string the exact output displayed by the program.

Why this answer

The code uses a try-except block to catch FileNotFoundError when attempting to open 'data.txt'. In the except block, it prints 'No file found' and then attempts to open 'backup.txt'. Since both files do not exist, the except block executes and prints 'No file found' before the second open attempt raises another FileNotFoundError, which is unhandled and terminates the program.

However, the question asks for the output, which is the print statement executed before the error.

Exam trap

Python Institute often tests the distinction between output produced before an unhandled exception and the exception itself, tricking candidates into thinking the program crashes without any output.

How to eliminate wrong answers

Option A is wrong because backup.txt does not exist, so its contents cannot be printed; the code would raise a FileNotFoundError on the second open attempt. Option B is wrong because the except block explicitly prints 'No file found' before the second open attempt, so something is output. Option C is wrong because while a FileNotFoundError does occur on the second open, the question asks for the output, not the exception; the print statement executes first, producing output.

27
MCQmedium

A developer is writing a script that processes user-uploaded CSV files. The script should attempt to read the file, and if a UnicodeDecodeError occurs, log a warning and skip the file. Which code snippet correctly achieves this without stopping the entire process?

A.try: read_file() except (UnicodeDecodeError, OSError): pass
B.try: read_file() except UnicodeDecodeError: log.warning('Skipping file')
C.try: read_file() except Exception: log.warning('Skipping file')
D.try: read_file() except UnicodeEncodeError: log.warning('Skipping file')
AnswerB

This is the correct approach because it deliberately catches only UnicodeDecodeError, which is the exception raised when reading and decoding bytes containing invalid UTF-8 or another specified codec. By logging a warning and doing nothing else, the handler reports the problem while allowing the surrounding loop to move on to the next uploaded file. More specific handlers like this leave unrelated exceptions—such as OSError or file-system errors—free to propagate, preserving their diagnostic value.

Why this answer

It catches only UnicodeDecodeError, which is the specific exception raised when a file contains invalid UTF-8 or other encoding issues. It logs a warning and then continues execution (the 'pass' is implied by the log statement, but the key is that the exception is handled without re-raising). This matches the requirement to skip the file without stopping the entire process.

Exam trap

Python Institute often tests the distinction between UnicodeDecodeError (input decoding) and UnicodeEncodeError (output encoding), and the trap here is that candidates confuse the two or use an overly broad except clause that hides bugs.

How to eliminate wrong answers

Option A is wrong because it catches both UnicodeDecodeError and OSError, but uses 'pass' instead of logging a warning, which fails the requirement to log a warning. Option C is wrong because it catches the broad Exception class, which would suppress all exceptions (including critical ones like KeyboardInterrupt or SystemExit) and violates best practices by being too broad. Option D is wrong because it catches UnicodeEncodeError, which is raised when encoding output (e.g., writing to a file), not when reading/decoding input; the correct exception for reading is UnicodeDecodeError.

28
MCQhard

Refer to the exhibit. What is the effect of using 'from None' in the raise statement?

A.It re-raises the original ValueError
B.It causes a syntax error
C.It suppresses the exception chain and only shows the TypeError
D.It chains the TypeError to the original ValueError
AnswerC

Using `from None` in a `raise` statement sets the `__suppress_context__` attribute of the exception to `True`. When the TypeError propagates, Python's default exception handler checks this flag and, because it is true, omits the implicit display of the original ValueError and its traceback. The final output therefore contains only the TypeError, either in the interactive shell or in a captured traceback.

Why this answer

In Python, 'raise TypeError(...) from None' explicitly suppresses the exception context, so the traceback shows only the TypeError and hides the original ValueError that triggered it. This is used when the original exception is irrelevant or confusing to the caller. Without 'from None', Python would chain the exceptions and display both.

Exam trap

The trap is assuming 'from None' means 'no chaining information at all' or that it re-raises the original — candidates must know it suppresses the display of the chained exception while still raising the new one, and that it is valid syntax.

How to eliminate wrong answers

Option A is wrong because 'from None' does not re-raise the original ValueError; it suppresses it from the displayed traceback, and the raised exception is the TypeError. Option B is wrong because 'raise ... from None' is valid Python 3 syntax (introduced in PEP 3134) and does not cause a syntax error. Option D is wrong because chaining the TypeError to the original ValueError is what happens by default or with 'from exc'; 'from None' does the opposite by suppressing the chain.

29
MCQmedium

A production script opens a configuration file with `open('config.ini', 'r')`. During a recent maintenance window, the file was replaced by a directory of the same name. The script now terminates with `IsADirectoryError`. The developer wants to catch this specific condition separately from a missing file and log a distinct message. Which `except` clause should be added?

A.except FileNotFoundError as e:
B.except IOError as e:
C.except OSError as e:
D.except IsADirectoryError as e:
AnswerD

IsADirectoryError is raised when the operating system reports that a path expected to be a regular file is actually a directory. Catching it by name lets the script log a specific message for that condition while allowing FileNotFoundError to fall through to its own handler. This directly satisfies the requirement to distinguish the two failures.

Why this answer

The directory-replacement scenario produces IsADirectoryError, a specific subclass of OSError raised when a path that should be a regular file resolves to a directory. Naming that exception in its own except clause isolates the condition and permits a tailored log message, while a separate FileNotFoundError clause can still handle a genuinely missing path. Broad parent handlers would merge the two cases.

Exam trap

The trap here is assuming that any file-access problem surfaces as FileNotFoundError or the generic OSError alias IOError, when a path that exists as a directory raises the distinct IsADirectoryError subclass.

30
MCQhard

Which of the following correctly raises a new exception while preserving the original traceback?

A.raise original_exception
B.raise ValueError('new')
C.raise ValueError('new') from original_exception
D.raise
AnswerC

This is the correct form for explicitly chaining a new exception to an existing one. The `from original_exception` clause makes Python assign the original to the new `ValueError`'s `__cause__` attribute, causing the traceback to present the original as the direct cause of the new exception. This preserves the debugging information from the original failure while still allowing a distinct exception type to be raised.

Why this answer

The `raise ... from original_exception` syntax in Python allows you to raise a new exception while chaining it to the original exception, preserving the original traceback. This is essential for debugging, as it shows both the new error and the root cause.

Exam trap

Python Institute often tests the distinction between re-raising the same exception (bare `raise` or `raise original_exception`) and raising a new exception with chaining (`raise ... from original_exception`), trapping candidates who think any `raise` preserves the traceback.

How to eliminate wrong answers

Option A is wrong because `raise original_exception` re-raises the exact same exception object, not a new one, so it does not create a new exception. Option B is wrong because `raise ValueError('new')` raises a brand-new exception without any reference to the original, losing the original traceback entirely. Option D is wrong because a bare `raise` can only be used inside an except block to re-raise the current exception; outside an except block it raises a RuntimeError, and it does not create a new exception.

31
MCQhard

A developer is creating a custom exception hierarchy for a library. The base exception is `LibraryError`. Which definition ensures that subclasses can be caught using the parent exception, but also allows distinguishing between different error types?

A.class LibraryError: pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
B.class LibraryError(BaseException): pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
C.class LibraryError(Exception): pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
D.class LibraryError(Exception): pass class FileError(Exception): pass class ParseError(Exception): pass
AnswerC

This is the canonical pattern: the library base class derives from Exception, so all library errors are ordinary, catchable exceptions; the specific subclasses then derive from that base class. Code catching LibraryError will also catch FileError and ParseError, while code can still catch either refined type independently. This gives a consistent API and lets the library evolve by adding new specific errors without breaking callers that rely on the base type.

Why this answer

It defines `LibraryError` as a subclass of `Exception`, which is the proper base class for all user-defined exceptions in Python. Subclasses `FileError` and `ParseError` inherit from `LibraryError`, so they can be caught with `except LibraryError` while still being distinguishable by their own type. This follows the standard Python exception hierarchy, where custom exceptions should derive from `Exception`, not `BaseException` or no base class.

Exam trap

Python Institute often tests the distinction between `Exception` and `BaseException`, and the trap here is that candidates mistakenly think any class named 'Error' is automatically an exception, or they choose Option B thinking `BaseException` is the correct base for all custom exceptions.

How to eliminate wrong answers

Option A is wrong because `LibraryError` does not inherit from `Exception`; it is a plain class, so it cannot be caught by a standard `except Exception` clause and does not integrate with Python's exception handling mechanism. Option B is wrong because `LibraryError` inherits from `BaseException`, which is reserved for system-exiting exceptions like `SystemExit` and `KeyboardInterrupt`; catching `BaseException` is discouraged as it can suppress critical signals. Option D is wrong because `FileError` and `ParseError` both inherit directly from `Exception` rather than from `LibraryError`, so they cannot be caught collectively as `LibraryError` and break the intended hierarchy.

32
MCQeasy

Which of the following is the correct way to open a file for writing in binary mode?

A.open('data.dat', 'wb')
B.open('data.dat', 'bw')
C.open('data.dat', 'br')
D.open('data.dat', 'w')
AnswerA

The mode string 'wb' is the correct Python file mode for binary writing. The first character 'w' specifies the operation (write), and the second character 'b' explicitly selects binary mode rather than text mode. This mode both creates the file if it does not exist and truncates it to zero length if it does, allowing you to write raw bytes without any encoding or newline translation.

Why this answer

The mode string 'wb' specifies both write ('w') and binary ('b') mode, which is the proper way to open a file for writing binary data in Python. The order of characters in the mode string is fixed: the file mode character ('r', 'w', 'a', etc.) must come first, followed by the optional 'b' for binary mode.

Exam trap

Python Institute often tests the strict ordering of mode characters in the open() function, expecting candidates to know that 'b' must always follow the read/write/append character, not precede it.

How to eliminate wrong answers

Option B is wrong because 'bw' reverses the required order — the mode character ('w') must precede the binary modifier ('b'), and Python will raise a ValueError for an invalid mode string. Option C is wrong because 'br' opens the file for reading in binary mode, not writing. Option D is wrong because 'w' opens the file for writing in text mode, not binary mode, which can cause data corruption when writing non-text data (e.g., images or serialized objects) due to newline translation.

33
MCQmedium

A developer is building a logging system that writes logs to a file. The system should handle disk-full situations gracefully without crashing the main application. Which approach is appropriate?

A.Check disk space before each write; if low, skip logging.
B.Wrap the entire application in a try/except that catches all exceptions.
C.Let the OSError propagate to the main program's exception handler.
D.Wrap the log write in a try/except that catches OSError and writes to stderr as fallback.
AnswerD

Wrapping only the write operation in a try/except that specifically catches OSError is the correct pattern: OSError is the parent class of errors like disk full, permission denied, and other I/O failures, so it captures the exact failure mode. Falling back to sys.stderr preserves the log entry and keeps the application running; if stderr itself fails, you can chain another exception or silently drop the record, but the primary failure is isolated. This targeted fallback also avoids hiding non-I/O bugs, unlike a global exception handler.

Why this answer

It uses a targeted try/except block around only the log write operation, catching OSError (which includes disk-full conditions) and falling back to stderr. This prevents the main application from crashing while still reporting the error, adhering to the principle of handling exceptions at the point where they occur and only when you can meaningfully recover.

Exam trap

Python Institute often tests the distinction between catching overly broad exceptions (Option B) versus catching specific exceptions (Option D), and the trap here is that candidates may think 'catching all exceptions' is a safe catch-all, but it actually hides programming errors and violates Python best practices.

How to eliminate wrong answers

Option A is wrong because checking disk space before each write is unreliable (race conditions, non-atomic check-then-act) and adds unnecessary overhead; it also does not handle other OSError scenarios like permission errors. Option B is wrong because wrapping the entire application in a blanket try/except that catches all exceptions (including KeyboardInterrupt, SystemExit) is an anti-pattern that masks bugs, violates the principle of catching specific exceptions, and can leave the application in an inconsistent state. Option C is wrong because letting OSError propagate to the main program's exception handler typically results in an unhandled exception that terminates the application, which is exactly what the developer wants to avoid.

34
Multi-Selecteasy

Which TWO of the following are built-in exceptions in Python? (Select exactly 2.)

Select 2 answers
A.InputError
B.ValueError
C.DataError
D.FileNotFoundError
E.CustomError
AnswersB, D

ValueError is a built-in exception and belongs to the Exception hierarchy, directly under Exception (and ultimately under BaseException). It is raised when a function receives an argument of the correct type but an inappropriate value—for example, int('abc') raises ValueError because the string cannot be converted to an integer. This distinguishes it from TypeError, which is for wrong types, and from other built-in exceptions that signal different error conditions.

Why this answer

ValueError is a built-in exception in Python, raised when a built-in operation or function receives an argument with the correct type but an inappropriate value, such as int('abc'). It is part of Python's standard exception hierarchy and does not require any import.

Exam trap

Python Institute often tests candidates by including plausible-sounding exception names like InputError or DataError that mimic real-world patterns but are not part of Python's built-in exception hierarchy, leading candidates to confuse custom or third-party exceptions with standard ones.

35
MCQhard

What is the output of the Python code after reading the config.txt file?

A.8080 (as string)
B.An exception is raised.
C.8080
D.'8080'
AnswerC

This is correct because the code reads the configuration value and converts it to an integer using int() (or a ConfigParser getint() call). The integer 8080 is then passed to print(), which displays the number without quotes. Since the conversion succeeds, the output is exactly the integer 8080.

Why this answer

The code reads the config.txt file and splits its content by newlines. The first line contains 'port=8080', and after splitting by '=', the second element is '8080'. The int() function converts this string to the integer 8080, which is then printed.

Option C is correct because the output is the integer 8080, not a string or quoted form.

Exam trap

The trap here is that candidates confuse the internal data type (string vs integer) with the printed output, assuming that because the source is a string, the output must also be a string or quoted, when in fact int() converts it to an integer and print() displays it without quotes.

How to eliminate wrong answers

Option A is wrong because the output is an integer, not a string; int() converts the string '8080' to an integer, so the printed value is 8080 without quotes. Option B is wrong because no exception is raised: the file is opened successfully, split operations are valid, and int('8080') is a valid conversion. Option D is wrong because the output is the integer 8080, not the string '8080' with quotes; print() outputs the integer representation without quotes.

36
MCQeasy

Consider the following code: import json try: with open('config.json') as f: data = json.load(f) except FileNotFoundError: print("Missing config file") except json.JSONDecodeError: print("Invalid JSON") except: print("Unexpected error") If the file 'config.json' exists but contains invalid JSON, what is printed?

A.Unexpected error
B.The program crashes with an unhandled exception.
C.Missing config file
D.Invalid JSON
AnswerD

Invalid JSON is correct because the file exists and is readable, but its content cannot be parsed by json.load() or json.loads(). The json module raises json.JSONDecodeError, a subclass of ValueError, when the data does not conform to JSON syntax. The program's except block catches this exception, confirming the specific outcome is "Invalid JSON" rather than any file-system error.

Why this answer

When the file exists but contains invalid JSON, attempting to parse it raises a json.JSONDecodeError. A program designed to handle this exception will catch it and print 'Invalid JSON', as indicated by option D. Options A and B are incorrect because the error is specifically a JSON parsing error, not an unexpected error or an unhandled crash.

Option C is incorrect because the file does exist, so no file-not-found error occurs.

Exam trap

Python Institute often tests the distinction between file existence errors (`FileNotFoundError`) and content parsing errors (`json.JSONDecodeError`), trapping candidates who assume any file problem results in a generic crash or a missing-file message.

How to eliminate wrong answers

Option A is wrong because 'Unexpected error' is not printed; the code has a specific handler for invalid JSON, not a generic catch-all. Option B is wrong because the program does not crash; the exception is caught, preventing an unhandled crash. Option C is wrong because 'Missing config file' is only printed if `FileNotFoundError` is raised, which requires the file to be absent, but the file exists (albeit with invalid content).

37
MCQmedium

A developer runs a script that reads records from a binary file. After a partial read, the storage device is unplugged, and the read() call raises OSError. The developer wants the script to retry the read a few times before giving up, but only for this transient I/O problem. Which exception should be caught to retry specifically on this failure?

A.RuntimeError
B.EOFError
C.OSError
D.IOError
AnswerC

OSError is the base class for I/O failures such as a device being unplugged, and read() raises it when the underlying read fails. Catching OSError around the read allows a bounded retry loop for this transient hardware problem, while still letting unrelated errors propagate. Because FileNotFoundError and PermissionError inherit from OSError, the handler should inspect errno or use a narrower subclass if those must be handled differently.

Why this answer

A transient device failure during read() surfaces as OSError, the common base for I/O errors. Catching it around the read permits a bounded retry while still allowing non-I/O exceptions to propagate. The other listed exceptions describe unrelated conditions and would not catch this failure, so they cannot drive the retry behavior the scenario requires.

Exam trap

The trap here is assuming that IOError is a separate, more specific exception from OSError, when in Python 3 IOError is just an alias for OSError.

38
MCQhard

A data-import tool must read a UTF-8 CSV file that occasionally contains bytes invalid for UTF-8. The tool should not crash, but it must record that replacement occurred so the operator can review the source. The developer opens the file with `open('data.csv', encoding='utf-8', errors='replace')` and reads it. Which outcome matches this configuration?

A.Each invalid byte sequence is replaced by U+FFFD, and the tool can scan for that character to detect and count problems.
B.Invalid bytes are silently removed from the decoded string, leaving no trace in the text.
C.The decoder substitutes a question mark character and logs a warning through the warnings module automatically.
D.Decoding invalid bytes raises UnicodeDecodeError, and the handler in the tool catches it per line.
AnswerA

The replace error handler substitutes the Unicode replacement character U+FFFD wherever the decoder encounters an invalid sequence. The resulting string is valid and the read does not raise, so the tool can search for U+FFFD to count and locate suspect regions. This matches the requirement to continue processing while recording that replacement occurred.

Why this answer

Passing errors='replace' to open installs an error handler that substitutes U+FFFD for every invalid byte sequence during decoding. The read completes without raising, producing a valid string that still carries visible markers of corruption. Scanning the decoded text for U+FFFD lets the tool count and report affected records, satisfying both the no-crash and traceability requirements.

Exam trap

The trap here is confusing errors='replace' with errors='ignore', assuming corruption disappears silently rather than leaving the visible U+FFFD replacement character in the decoded string.

39
Multi-Selecthard

Which THREE of the following are true about Python's exception hierarchy?

Select 3 answers
A.KeyboardInterrupt inherits from BaseException.
B.SystemExit inherits from BaseException.
C.IOError is a separate class from OSError.
D.ZeroDivisionError inherits from ArithmeticError.
E.GeneratorExit inherits from Exception.
AnswersA, B, D

KeyboardInterrupt is a true statement because KeyboardInterrupt is a direct subclass of BaseException, not of Exception. This design ensures that a KeyboardInterrupt triggered by Ctrl+C propagates outward even when code has a broad `except Exception:` handler. Catching it accidentally would prevent clean interruption and could leave the program in an inconsistent state, so it must be caught explicitly with `except KeyboardInterrupt` or a bare `except:`. The hierarchy deliberately places user-initiated termination outside the ordinary exception family.

Why this answer

`KeyboardInterrupt` inherits directly from `BaseException`, not from `Exception`. This design ensures that `KeyboardInterrupt` (raised by Ctrl+C) is not caught by a generic `except Exception:` clause, allowing the program to be interrupted even when broad exception handling is in place.

Exam trap

Python Institute often tests the misconception that `GeneratorExit` inherits from `Exception` (it actually inherits from `BaseException`), and that `IOError` is a separate class from `OSError` (it is an alias in Python 3).

40
MCQhard

When should you raise a specific exception class rather than a generic Exception?

A.When different error conditions require different handling.
B.Always raise Exception for simplicity.
C.Specific exceptions cannot be created; only built-in ones can be used.
D.Only when performance is a concern.
AnswerA

Specific exceptions allow callers to catch precisely the conditions they can handle, using except clauses that match the exception type. Without distinct types, you would have to inspect messages or attributes, which is brittle and error-prone. Thus, raising a specific exception class is warranted when different error conditions require different handling, because the exception type itself becomes part of the API contract.

Why this answer

Raising a specific exception class (e.g., ValueError, KeyError, or a custom subclass) allows the caller to catch and handle each error condition differently using separate except blocks. Using a generic Exception forces all errors into a single handler, which can mask distinct failure modes and make debugging harder. This aligns with Python's EAFP (Easier to Ask for Forgiveness than Permission) idiom, where precise exception types enable fine-grained error recovery.

Exam trap

Python Institute often tests the misconception that generic Exception is simpler or sufficient, but the trap is that it forces all errors into one catch-all, which hides the need for distinct handling logic and violates Pythonic best practices for exception granularity.

How to eliminate wrong answers

Option B is wrong because always raising generic Exception violates the principle of exception specificity, making it impossible for callers to distinguish between error types without inspecting the message string, which is fragile and discouraged. Option C is wrong because Python allows creation of custom exception classes by subclassing Exception (or any other built-in exception), enabling domain-specific error handling. Option D is wrong because performance is rarely a concern when choosing exception types; the decision should be based on semantic clarity and handling requirements, not optimization.

41
Multi-Selecthard

Which THREE of the following are true about the `with` statement for file handling?

Select 3 answers
A.It can only be used with files.
B.It can only handle one file at a time.
C.It uses the __enter__ and __exit__ methods of the file object.
D.It ensures the file is closed even if an exception occurs inside the block.
E.It automatically closes the file when the block exits.
AnswersC, D, E

When entering a `with` block, Python calls the `__enter__` method on the context manager and assigns its return value to the `as` variable. Upon block exit, it always calls the `__exit__` method, which for a file object performs the actual closing operation. This pair of methods forms the core of the context manager protocol, and the `with` statement is simply a wrapper that guarantees both calls.

Why this answer

The `with` statement relies on the context management protocol, which requires the object to implement the `__enter__` and `__exit__` methods. When a file object is used with `with`, its `__enter__` method returns the file object itself, and its `__exit__` method is called upon block exit to handle cleanup, such as closing the file.

Exam trap

Python Institute often tests the misconception that `with` is only for files, but the trap here is that candidates may also incorrectly think it can only handle one file at a time, while Python actually supports multiple context managers in a single `with` statement.

42
MCQmedium

A file is opened with open('test.txt', 'r'). The file object's tell() method returns 0. After reading 10 characters, what does tell() return?

A.File size
B.0
C.-1
D.10
AnswerD

After reading 10 bytes (or characters, in text mode on most platforms) from the beginning of the file, the file pointer has advanced from offset 0 to offset 10. Calling tell() immediately after the read returns 10, which correctly reflects that new position in the stream. This is why 10 is the accurate answer: tell() always mirrors the exact number of bytes the read operation has consumed from the start.

Why this answer

The `tell()` method returns the current position of the file pointer in bytes from the beginning of the file. After reading 10 characters (each being 1 byte in a typical text file), the pointer advances by 10 bytes, so `tell()` returns 10.

Exam trap

Python Institute often tests the misconception that `tell()` returns the number of characters read or the file size, when in fact it returns the byte offset from the start of the file.

How to eliminate wrong answers

Option A is wrong because `tell()` does not return the file size; it returns the current offset, not the total length. Option B is wrong because the file pointer moves after reading, so it cannot remain at 0. Option C is wrong because `tell()` never returns -1; it always returns a non-negative integer representing the byte offset.

43
Multi-Selectmedium

A backup utility writes a manifest with `with open('manifest.txt', 'w') as out:`. The developer needs to ensure that partial writes are not silently left in the file when an exception occurs mid-loop. Which two statements about using a try/except/else/finally structure around this write loop are correct? (Choose two.)

Select 2 answers
A.The finally block executes even if an except clause handles the exception and the handler itself raises a new exception.
B.Code in the else block runs before the except clauses are evaluated, so it can change which handler is selected.
C.A return statement inside the try block prevents the finally block from executing.
D.The else block runs only when the try block completes without raising an exception.
E.If an except clause handles the exception, the finally block is skipped because the error was already resolved.
AnswersA, D

finally is guaranteed to run during the unwinding of the try statement regardless of whether an exception occurred, was handled, or was replaced by a new exception inside a handler. This guarantee is what makes finally suitable for cleanup such as removing a temporary manifest file or releasing a lock.

Why this answer

In a try/except/else/finally statement, else runs only when the try suite finishes without an exception, and finally runs unconditionally during unwinding, including when a handler raises or when try exits via return. Those two guarantees let the developer mark success in else and perform unconditional cleanup in finally, protecting against partially written manifests.

Exam trap

The trap here is assuming that a handled exception or an early return cancels the finally suite, when finally is designed to run during every form of exit from the statement.

44
MCQhard

A programmer writes a context manager to manage a temporary file. The class implements __enter__ to open the file and return the handle, and __exit__ to close it. During the with body, an exception is raised. The programmer wants the exception to propagate after cleanup. What should __exit__ return in this case?

A.True
B.The file handle returned by open()
C.None, only after re-raising the exception with raise
D.False
AnswerD

The __exit__ method receives the exception type, value, and traceback, and its return value controls suppression. Returning False (or a falsy value such as None) means the exception is not suppressed and will propagate after __exit__ finishes. In this scenario the programmer wants the exception to propagate, so returning False after closing the file satisfies the requirement while still performing cleanup.

Why this answer

The __exit__ return value is a suppression flag: a falsy result lets the exception propagate, while a truthy result suppresses it. Since the goal is to clean up the temporary file and still surface the error, returning False is correct. Returning a handle or re-raising inside __exit__ would either hide the exception or replace it with a different one.

Exam trap

The trap here is assuming that __exit__ returning the file handle is a valid cleanup pattern, when any truthy return value suppresses the exception.

45
Multi-Selecthard

Which THREE of the following statements about Python's 'with' statement are true? (Select exactly 3)

Select 3 answers
A.It can be used with any object that implements __enter__ and __exit__ methods.
B.It guarantees that the __exit__ method is called even if an exception occurs inside the block.
C.It can be used with multiple context managers separated by commas.
D.It eliminates the need for try/finally blocks for resource management.
E.It can only be used with file objects.
AnswersA, B, C

The 'with' statement works with any object implementing the context manager protocol, namely __enter__ and __exit__. This duck-typing behaviour means files, locks, sockets and custom classes all qualify, without requiring inheritance from a specific base class.

Why this answer

Option A is correct because the context manager protocol is defined precisely by the presence of __enter__ and __exit__ methods, so any object implementing both can be used with 'with'. Option B is correct because the 'with' statement's semantics ensure __exit__ is invoked when the block exits, whether normally or via an exception, which is the core guarantee of the protocol. Option C is correct because Python supports 'with A() as a, B() as b:' syntax, allowing multiple context managers separated by commas (equivalent to nested with statements).

Option D is not marked correct because while 'with' often replaces try/finally for resource cleanup, it does not eliminate the need for try/finally in all cases, such as when no context manager exists or when cleanup logic must run without one. Option E is not marked correct because 'with' works with any context manager, not only file objects; files are just a common example.

Exam trap

Python Institute often tests the misconception that the 'with' statement is only for file I/O, leading candidates to incorrectly select option E, while also testing the understanding that it simplifies but does not replace try/finally blocks, making option D a distractor for those who overestimate its capabilities.

46
Drag & Dropmedium

Drag and drop the steps to serialize a Python object to JSON using the json module into the correct order.

Drag or tap steps into the slots.

Steps
Order
1Step 1
2Step 2
3Step 3
4Step 4

Why this order

Serialization to JSON involves importing json, preparing data, using dumps for string or dump for file output.

47
MCQmedium

A script uses `with open('data.bin', 'rb') as f:` to read binary data. Within the block, which method should be used to read exactly 4 bytes?

A.f.read(4)
B.f.seek(4)
C.f.readline()
D.f.read()
AnswerA

Calling f.read(4) on a binary file opened with mode 'rb' reads at most 4 bytes from the current file position, returning them as a bytes object. This is precisely the intended operation for reading a fixed-size chunk, which is essential when parsing binary formats that store data in fixed-width fields, such as integers or headers. The size argument caps the read length, so the file pointer advances by exactly the number of bytes actually read, and it handles end-of-file gracefully by returning fewer than 4 bytes.

Why this answer

The `read(n)` method reads exactly `n` bytes from the file object when the file is opened in binary mode (`'rb'`). Since the question specifies reading exactly 4 bytes, `f.read(4)` is the correct and direct approach. This method returns a bytes object of up to `n` bytes, but if the file has at least 4 bytes remaining, it will return exactly 4.

Exam trap

Python Institute often tests the distinction between `read()` (reads entire file), `read(n)` (reads exactly n bytes), and `seek()` (moves pointer without reading), and the trap here is that candidates may confuse `seek(4)` with reading 4 bytes, or assume `read()` without arguments reads a fixed number of bytes.

How to eliminate wrong answers

Option B is wrong because `f.seek(4)` moves the file pointer to byte offset 4 from the beginning, but does not read any data. Option C is wrong because `f.readline()` reads until a newline byte (`\n`) or EOF, which is not guaranteed to return exactly 4 bytes and is intended for text-based line reading, not fixed-size binary reads. Option D is wrong because `f.read()` with no argument reads the entire remaining contents of the file into memory, which will almost certainly not be exactly 4 bytes unless the file itself is exactly 4 bytes long.

48
MCQmedium

What is the output of the following code? try: print(1/0) except: print('err') finally: print('fin')

A.fin err
B.fin
C.err fin
D.err
AnswerC

After an exception is raised in the try block, Python finds the matching except clause and executes its body, printing "err". The finally clause then executes unconditionally as part of exception handling, printing "fin" after the except handler completes. Thus the full and correct output is "err fin".

Why this answer

When a division by zero occurs, Python raises a ZeroDivisionError, which is caught by the bare except clause, printing 'err'. The finally clause always executes after the except block, printing 'fin'. Thus the output is 'err' followed by 'fin'.

Exam trap

Python Institute often tests the order of execution in try/except/finally blocks, specifically that the except block runs before the finally block when an exception is caught, and that the finally block always executes even if no exception occurs.

How to eliminate wrong answers

Option A is wrong because it shows 'fin err', implying the finally block runs before the except block, but in Python the except block runs first when an exception is caught. Option B is wrong because it shows only 'fin', ignoring that the except block prints 'err' when the exception is caught. Option D is wrong because it shows only 'err', omitting the finally block which always executes regardless of whether an exception occurs or is caught.

49
MCQeasy

A developer writes a function that reads a file and processes its content. The function should handle the case where the file does not exist without catching other I/O errors. Which exception should be caught?

A.PermissionError
B.IOError
C.OSError
D.FileNotFoundError
AnswerD

FileNotFoundError is the specific built-in exception that Python raises when an attempt to open or access a file path cannot succeed because the path does not exist, typically with errno ENOENT. For a read operation, open(path, 'r') will immediately raise it if the file is not present before any other processing occurs. Because it is narrowly scoped, catching FileNotFoundError lets the developer provide exactly the right fallback—like creating the file or printing a meaningful message—without masking permission problems or unrelated OS failures.

Why this answer

`FileNotFoundError` is a specific subclass of `OSError` that is raised exactly when a file or directory is requested but does not exist. By catching only `FileNotFoundError`, the function handles the missing-file scenario without masking other I/O errors such as permission issues or disk failures, which is the precise requirement stated in the question.

Exam trap

Python Institute often tests the Python exception hierarchy, and the trap here is that candidates mistakenly choose `IOError` or `OSError` because they are broader and seem 'safer,' but the question explicitly requires handling only the missing-file case without catching other I/O errors.

How to eliminate wrong answers

Option A is wrong because `PermissionError` is raised when the file exists but the process lacks the necessary permissions (e.g., read or write access), not when the file is missing. Option B is wrong because `IOError` is an alias for `OSError` in Python 3 and is too broad; catching it would also catch unrelated I/O errors like permission or disk errors, violating the requirement to avoid catching other I/O errors. Option C is wrong because `OSError` is the parent class for many file-related exceptions (including `FileNotFoundError`, `PermissionError`, etc.); catching it would handle all OS-level errors, not just the missing-file case.

50
MCQmedium

A developer wants to ensure that a file is always closed after writing, even if an exception occurs. Which approach is considered best practice in Python?

A.Use try/finally with explicit f.close()
B.Rely on the garbage collector to close the file
C.Use try/except/finally with f.close() in both except and finally
D.Use the with statement: with open('file.txt', 'w') as f: ...
AnswerD

Using the with statement is the idiomatic Pythonic solution because it leverages the context manager protocol: open() returns a file object whose __enter__ and __exit__ methods are invoked by with, guaranteeing that __exit__ calls close() even if the body raises an exception or encounters a return/break/continue. This automatically flushes buffered writes and releases the OS file descriptor deterministically at the end of the block. It also handles the case where open() itself fails by never entering the block, so no file object needs cleanup, and it expresses the intent of scoped resource management clearly.

Why this answer

The `with` statement in Python implements a context manager that automatically calls the file's `__exit__` method, which closes the file even if an exception occurs inside the block. This is the idiomatic and recommended approach for resource management, as it guarantees cleanup without requiring explicit `close()` calls.

Exam trap

Python Institute often tests the misconception that `try/finally` with explicit `close()` is equivalent to the `with` statement, but the trap is that the `with` statement is the explicitly recommended best practice in the Python documentation and PEP 343, making it the correct answer over more manual approaches.

How to eliminate wrong answers

Option A is wrong because while `try/finally` with explicit `f.close()` does ensure the file is closed, it is more verbose and error-prone than the `with` statement, and it is not considered best practice in modern Python. Option B is wrong because relying on the garbage collector to close the file is unreliable — the garbage collector may not run immediately, and file descriptors are a limited OS resource that should be released deterministically. Option C is wrong because placing `f.close()` in both `except` and `finally` is redundant and unnecessary; the `finally` block alone guarantees execution regardless of exceptions, so duplicating the call in `except` adds no benefit and can lead to double-close errors if not handled carefully.

51
MCQeasy

Which mode should be used when opening a file for writing such that new content is appended to the end without truncating existing content?

A.'x'
B.'r+'
C.'w'
D.'a'
AnswerD

The 'a' (append) mode opens the file for writing and places the file pointer at the end of the existing content, so every write extends the file without overwriting or truncating it. If the file is missing, Python creates a new empty file, matching the requirement to write new data while preserving what is already there. This is the only standard write mode designed specifically for adding to the end of a file.

Why this answer

('a') is correct because the 'a' mode opens a file for appending, which means new data is written to the end of the file without truncating any existing content. This is the standard behavior defined in Python's open() function for append mode.

Exam trap

Python Institute often tests the confusion between 'w' (which truncates) and 'a' (which appends), and candidates mistakenly choose 'w' thinking it simply writes without realizing it destroys existing data.

How to eliminate wrong answers

Option A ('x') is wrong because 'x' is exclusive creation mode — it opens a file for writing but fails if the file already exists, and it does not append. Option B ('r+') is wrong because 'r+' opens a file for both reading and writing, but it does not automatically position the write pointer at the end; it starts at the beginning and can overwrite existing content. Option C ('w') is wrong because 'w' opens a file for writing and truncates the file to zero length, destroying all existing content.

52
MCQeasy

A developer writes a script that reads a configuration file. If the file does not exist, the program should print an error and continue. Which code snippet correctly implements this behavior?

A.try: open('config.txt') except FileNotFoundError: print('File not found')
B.f = open('config.txt', 'r') if not f: print('File not found')
C.try: f = open('config.txt') except: print('File not found')
D.try: with open('config.txt') as f: pass except Exception: print('File not found')
AnswerA

This snippet is correct because it confines the error handling to exactly the condition the developer cares about: the file's absence. When the interpreter evaluates open('config.txt'), a missing config file raises a FileNotFoundError (a subclass of OSError), and that exception is caught and handled specifically. Other I/O problems, such as a permission denial or a path that is actually a directory, raise different OSError subclasses and are allowed to propagate, which preserves diagnostic accuracy.

Why this answer

It uses a `try` block to attempt opening the file and catches only `FileNotFoundError`, which is the specific exception raised when the file does not exist. This allows the program to print an error and continue execution without crashing, precisely matching the requirement.

Exam trap

Python Institute often tests the distinction between catching a specific exception versus a broad or bare `except`, and the trap here is that candidates may think any `try-except` works, overlooking the requirement to catch only `FileNotFoundError` for precise error handling.

How to eliminate wrong answers

Option B is wrong because `open()` does not return a falsy value when the file is missing; it raises a `FileNotFoundError` before any assignment occurs, so the `if not f` check is never reached. Option C is wrong because it uses a bare `except:` clause, which catches all exceptions (including unrelated ones like `KeyboardInterrupt` or `PermissionError`), violating best practices and potentially masking bugs. Option D is wrong because it catches the overly broad `Exception` class, which is too general and could hide unexpected errors; the requirement specifically needs to catch only `FileNotFoundError`.

53
MCQhard

Refer to the exhibit. What does the 'from None' clause do in the second raise statement?

A.It causes the original exception to be ignored.
B.It prevents chaining of exceptions, so only the final exception is displayed.
C.It causes both exceptions to be raised simultaneously.
D.It replaces the original exception with a new one.
AnswerB

When you write `raise NewException from None`, Python's exception-handling machinery sets `__suppress_context__ = True` on the new exception. This disables the automatic chaining that normally links the current exception to the one that was being handled, which would otherwise show as "During handling of the above exception, another exception occurred" in the traceback. As a result, only the final exception's traceback is displayed, and the original, caught exception is not shown as context, though it still exists internally.

Why this answer

In Python, the 'from None' clause in a raise statement explicitly suppresses exception chaining. Normally, when an exception is raised inside an except block, Python automatically chains the new exception to the original one using the __cause__ attribute. Using 'raise NewException from None' sets __cause__ to None, which prevents the interpreter from displaying the original exception's traceback, so only the final exception is shown.

Exam trap

The PCAP exam often tests the distinction between suppressing chaining ('from None') and replacing or ignoring the original exception, leading candidates to mistakenly think the original exception is lost or ignored entirely.

How to eliminate wrong answers

Option A is wrong because 'from None' does not ignore the original exception; the original exception still occurs and can be accessed programmatically, but its traceback is suppressed. Option C is wrong because Python does not support raising two exceptions simultaneously; 'from None' only controls chaining, not concurrent raising. Option D is wrong because 'from None' does not replace the original exception; it merely prevents the automatic chaining that would display the original exception's context.

54
MCQhard

Which of the following exception classes is NOT a direct subclass of Exception in Python?

A.IOError
B.SystemExit
C.StopIteration
D.ValueError
AnswerB

SystemExit is the correct answer because it inherits directly from BaseException rather than from Exception. Unlike IOError, StopIteration, and ValueError—all of which are descendants of Exception—SystemExit bypasses the Exception class entirely. This deliberate design lets SystemExit (along with KeyboardInterrupt) propagate even when code catches Exception, so it is the only listed class that is not a subclass of Exception.

Why this answer

SystemExit is not a direct subclass of Exception; it inherits from BaseException instead. This is because SystemExit, along with KeyboardInterrupt and GeneratorExit, is intended to signal that the interpreter should exit, and catching it with a generic except Exception clause would be inappropriate. All other options (IOError, StopIteration, ValueError) are direct subclasses of Exception.

Exam trap

Python Institute often tests the distinction between BaseException and Exception, trapping candidates who assume all built-in exceptions inherit from Exception, when in fact SystemExit, KeyboardInterrupt, and GeneratorExit are direct subclasses of BaseException.

How to eliminate wrong answers

Option A is wrong because IOError is a direct subclass of Exception (and in Python 3, it is an alias of OSError, which also inherits from Exception). Option C is wrong because StopIteration is a direct subclass of Exception, used to signal the end of an iterator. Option D is wrong because ValueError is a direct subclass of Exception, raised when a built-in operation or function receives an argument with the right type but an inappropriate value.

55
MCQeasy

Refer to the exhibit. If the file config.cfg exists but the user does not have read permission, what will be printed?

A.An unhandled exception is raised
B.'Permission denied'
C.Nothing; the program continues silently
D.'File not found'
AnswerB

Since config.cfg exists but the process lacks the required read permission, the file's opening operation raises `PermissionError`. The corresponding `except PermissionError` clause catches it and executes its print statement, producing `'Permission denied'` as the program's visible output. This is the expected, handled outcome.

Why this answer

When `open()` is called on a file that exists but the user lacks read permission, Python raises a `PermissionError`. Since no exception handling is present, the exception is unhandled and Python prints a traceback to stderr which includes the error message `'Permission denied'` (among other details). Option B correctly identifies the permission-denied message that appears in the output.

Exam trap

Python Institute often tests the distinction between file existence errors (FileNotFoundError) and permission errors (PermissionError), and candidates mistakenly assume that a missing file is the only possible file-related exception.

How to eliminate wrong answers

Option A is wrong because an unhandled exception is indeed raised, but the question asks what will be printed — the exception's error message ('Permission denied') is printed, not just an unhandled exception without output. Option C is wrong because Python does not silently continue when a file permission error occurs; it raises an exception that must be caught to avoid termination. Option D is wrong because the file config.cfg exists (as stated in the question), so a 'File not found' error would only occur if the file did not exist, which is not the case here.

56
Multi-Selectmedium

Which TWO of the following are appropriate techniques for logging exception details in Python? (Select exactly 2)

Select 2 answers
A.Using print(e.args)
B.Using traceback.format_exc()
C.Using sys.exc_info()
D.Using raise without argument
E.Using logging.exception() inside except block
AnswersB, E

Calling traceback.format_exc() inside an except block returns a complete, pre-formatted traceback string that includes the exception type, message, and the entire call stack at the point of failure. This string can be directly written to a log file, sent to a monitoring system, or stored for later analysis, making it an appropriate technique for capturing exception details. Unlike print(e.args), it preserves the full execution context needed to diagnose the root cause.

Why this answer

`traceback.format_exc()` returns the full traceback as a string, which can be logged or printed to capture detailed exception context. Option E is correct because `logging.exception()` automatically includes the traceback of the current exception when called inside an `except` block, making it the idiomatic way to log exceptions in Python.

Exam trap

Python Institute often tests the distinction between merely accessing exception data (like `e.args` or `sys.exc_info()`) and actually formatting or logging it properly, so candidates mistakenly think any function that touches exception info qualifies as a 'logging technique'.

57
MCQhard

Refer to the exhibit. A developer ran the script and saw the above traceback. The intended behavior was to load a JSON configuration file, and if the file is missing, create a default config. What is the most likely root cause of the second exception (NameError)?

A.The variable 'f' was not defined due to the FileNotFoundError.
B.The script did not import the json module.
C.The config.json file exists but is empty.
D.The file was opened in binary mode instead of text mode.
AnswerB

NameError: name 'json' is not defined means Python could not find a binding for the name 'json' in any accessible scope. The json module is part of the standard library but is not automatically loaded; it must be brought into scope with an explicit import json statement. Since the script calls json.load(f) without having imported json, the name lookup fails at runtime. This is the classic missing-import error and is unrelated to the file's existence, content, or open mode.

Why this answer

The traceback shows a NameError for 'json.loads', which indicates that the name 'json' is not defined in the current namespace. This occurs when the script attempts to call json.loads() without first importing the json module. The intended behavior of loading a JSON configuration file requires the json module to parse the file content, and its absence causes the NameError exception.

Exam trap

Python Institute often tests the distinction between file I/O exceptions (like FileNotFoundError) and name resolution errors (NameError), trapping candidates who focus on the file handling part of the traceback rather than recognizing that the second exception is about an undefined module name.

How to eliminate wrong answers

Option A is wrong because the NameError occurs after the FileNotFoundError is handled (the traceback shows the exception chain), and the variable 'f' is not referenced in the json.loads() call; the error is about the name 'json', not 'f'. Option C is wrong because an empty file would not cause a NameError; it would cause a json.JSONDecodeError when trying to parse empty content, not a missing name. Option D is wrong because opening a file in binary mode (e.g., 'rb') would not cause a NameError; it would affect how the file content is read (bytes vs string), but the json.loads() function can still be called if the module is imported, and the error would be a TypeError or similar, not a NameError.

58
MCQeasy

Refer to the exhibit. The above log shows an unhandled exception that caused the program to crash. The developer wants to handle this exception and log the error without crashing. Which exception type should be caught in the main code to capture this specific error?

A.BaseException
B.ValueError
C.OSError
D.Exception
AnswerB

The log explicitly shows "ValueError: ..." being raised. This is the precise exception type that occurred, so the appropriate handler is except ValueError. It is specific to the problem: a function received an argument of the right type but an inappropriate value. Catching this specific exception allows targeted recovery without swallowing unrelated errors.

Why this answer

The traceback shows that a ValueError was raised. To handle this specific exception, the code should catch ValueError. Catching Exception would also work but is less specific.

Catching BaseException catches system-exit exceptions. OSError is unrelated.

59
MCQhard

A Python application processes user-uploaded files. The requirement is to catch any I/O-related exception while reading the file, but not to catch KeyboardInterrupt or SystemExit. Which exception type should be caught?

A.OSError
B.IOError
C.Exception
D.BaseException
AnswerA

OSError is the correct choice because it is the built-in exception class for all operating-system-related I/O failures—file not found, permission denied, disk full, or invalid file descriptor—and it deliberately excludes system-exiting exceptions like KeyboardInterrupt and SystemExit. Catching OSError lets the application handle upload failures gracefully without masking fatal interpreter or user-interrupt conditions. Since Python 3.3, IOError is an alias of OSError, so OSError is the canonical, forward-compatible name to use.

Why this answer

`OSError` is the base class for all I/O-related exceptions in Python 3, including file reading errors like `FileNotFoundError` and `PermissionError`. It does not catch `KeyboardInterrupt` or `SystemExit`, which inherit directly from `BaseException`, not `Exception`. This makes `OSError` the precise choice for catching I/O errors while allowing program termination signals to propagate.

Exam trap

Python Institute often tests the Python 3 exception hierarchy change where `IOError` is no longer a separate class but an alias of `OSError`, tempting candidates to pick the familiar `IOError` from Python 2 instead of the correct `OSError`.

How to eliminate wrong answers

Option B is wrong because `IOError` was merged into `OSError` in Python 3 and is now an alias; catching `IOError` would work in Python 2 but is deprecated and not the recommended modern approach. Option C is wrong because `Exception` catches all built-in exceptions that inherit from it, including `KeyboardInterrupt` and `SystemExit` (which inherit from `BaseException`), violating the requirement to not catch those. Option D is wrong because `BaseException` is the root of all exceptions and would catch everything, including `KeyboardInterrupt` and `SystemExit`, which is explicitly disallowed.

60
MCQmedium

Refer to the exhibit. If /var/data/in.csv does not exist, what exception is raised?

A.configparser.NoSectionError
B.PermissionError
C.IndexError
D.FileNotFoundError
AnswerD

Opening /var/data/in.csv with the built-in open() function raises FileNotFoundError when the path does not exist, satisfying the stem's missing-file constraint. This OSError subclass carries errno ENOENT and is raised before any read occurs, so no other exception type applies here.

Why this answer

When a file does not exist and you attempt to open it for reading using the built-in `open()` function, Python raises a `FileNotFoundError`. This is a subclass of `OSError` and is the standard exception for missing files in Python 3. The question explicitly states that `/var/data/in.csv` does not exist, so the correct exception is `FileNotFoundError`.

Exam trap

A common trap in Python exams is confusing FileNotFoundError with PermissionError. When a file does not exist, Python raises FileNotFoundError, not PermissionError. Always verify the file's existence before attempting to open it.

How to eliminate wrong answers

Option A is wrong because `configparser.NoSectionError` is raised by the `configparser` module when a requested section is not found in a configuration file, not when a file is missing. Option B is wrong because `PermissionError` is raised when the file exists but the user lacks the necessary permissions to read or write it, not when the file is absent. Option C is wrong because `IndexError` is raised when a sequence subscript is out of range, such as accessing a list element with an invalid index, and has no relation to file I/O operations.

61
Multi-Selectmedium

Which TWO of the following are valid ways to read a file line by line without loading the entire file into memory?

Select 2 answers
A.lines = list(f)
B.for line in f:
C.contents = f.read().split('\n')
D.while True: line = f.readline(); if not line: break
E.lines = f.readlines()
AnswersB, D

This is the canonical line-by-line iteration in Python. The file object is an iterator that yields one line at a time, reading from disk lazily as the loop advances, so only one line resides in memory at a time. This is memory-efficient and the recommended way to process text files sequentially.

Why this answer

Iterating directly over a file object with `for line in f:` reads one line at a time from the file's internal buffer, never loading the entire file into memory. This is the idiomatic and memory-efficient way to process large files line by line in Python.

Exam trap

Python Institute often tests the distinction between methods that load the entire file into memory (like `readlines()`, `read().split()`, and `list(f)`) versus the iterator protocol that processes lines lazily, and candidates frequently confuse `list(f)` as being lazy because it uses the file object.

62
MCQhard

Consider the following code snippet: try: x = int(input()) y = 10 / x print(y) except ZeroDivisionError: print('Division by zero') except ValueError: print('Invalid integer') If the user enters '0', what is the output?

A.No output
B.Both 'Invalid integer' and 'Division by zero'
C.Division by zero
D.Invalid integer
AnswerC

When the user enters '0', int('0') returns 0 without error, so the try block proceeds to evaluate 10 / 0. This expression raises ZeroDivisionError, and Python matches it to the except ZeroDivisionError clause, causing 'Division by zero' to be printed. The output is exactly that message, demonstrating that an exception raised by an arithmetic operation is handled by its specific handler.

Why this answer

When the user enters '0', the input is successfully converted to the integer 0 by int(), so no ValueError occurs. Then 10 / 0 raises a ZeroDivisionError, which is caught by the except ZeroDivisionError block, printing 'Division by zero'. Option C is correct because the code never reaches the ValueError handler.

Exam trap

Python Institute often tests the order of exception handling and the fact that int('0') succeeds, leading candidates to mistakenly think a ValueError occurs or that both exceptions could fire.

How to eliminate wrong answers

Option A is wrong because the ZeroDivisionError is raised and caught, so there is output ('Division by zero'), not no output. Option B is wrong because only one exception occurs (ZeroDivisionError), not both; the ValueError handler is only triggered if int() fails, which it does not here. Option D is wrong because 'Invalid integer' would only print if the input could not be converted to an integer (e.g., entering 'abc'), but '0' is a valid integer string.

63
MCQeasy

What will be the output of the following code? try: print(1/0) except: print('error') else: print('no error') finally: print('done')

A.no error\ndone
B.error\nno error\ndone
C.done
D.error\ndone
AnswerD

This is the correct output because the try block raises an exception that is caught by the except handler, which immediately prints 'error'. The else clause, which would print 'no error', is skipped because an exception was raised. The finally clause then unconditionally executes and prints 'done', producing exactly two lines: 'error' and 'done' in that order.

Why this answer

The code raises a ZeroDivisionError when attempting 1/0, which is caught by the bare except clause, printing 'error'. The else clause is skipped because an exception occurred. The finally clause always executes, printing 'done'.

Thus the output is 'error' followed by 'done'.

Exam trap

Python Institute often tests the order of execution in try/except/else/finally, specifically that the else block is skipped when an exception occurs, and that finally always runs, leading candidates to mistakenly include 'no error' or omit 'error'.

How to eliminate wrong answers

Option A is wrong because it suggests the except block was skipped and the else block ran, which would only happen if no exception occurred; but 1/0 raises an exception. Option B is wrong because it includes 'no error' from the else block, which is never executed when an exception is caught. Option C is wrong because it omits 'error', implying the except block did not execute, but the exception is indeed caught and handled.

64
MCQeasy

Which of the following is the correct way to open a file for writing in text mode, ensuring that if the file already exists it will be overwritten?

A.open('file.txt', 'x')
B.open('file.txt', 'w')
C.open('file.txt', 'r+')
D.open('file.txt', 'a')
AnswerB

The 'w' mode opens the file for writing and truncates it to zero bytes if it exists, or creates a new file if it does not. This makes it the standard choice for write operations that should replace the entire contents of the file. It is the correct mode here because it permits immediate writing to the file with the expectation that prior content will be discarded.

Why this answer

The 'w' mode opens the file for writing in text mode and truncates the file to zero length if it exists, or creates a new file if it does not. This ensures any existing content is overwritten, which matches the requirement.

Exam trap

Python Institute often tests the distinction between 'w' and 'x' modes, where candidates mistakenly choose 'x' thinking it creates a new file for writing, but forget that 'x' raises an error if the file already exists, failing the overwrite requirement.

How to eliminate wrong answers

Option A is wrong because 'x' mode opens the file for exclusive creation, raising a FileExistsError if the file already exists, rather than overwriting it. Option C is wrong because 'r+' mode opens the file for both reading and writing without truncating it, so existing content is preserved and not overwritten unless explicitly written over. Option D is wrong because 'a' mode opens the file for appending, writing data at the end of the file without truncating or overwriting existing content.

65
MCQeasy

A developer needs to write binary data to a file. Which file mode should be used to open the file for writing in binary mode without truncating it if it already exists?

A.'wb'
B.'rb'
C.'ab'
D.'wb+'
AnswerC

'ab' opens a file for binary append: if the file exists, the file pointer is positioned at the end so all writes are appended after existing data, and the original content is never truncated. If the file does not exist, a new empty file is created automatically. This makes 'ab' the appropriate choice when writing binary data without destroying prior content.

Why this answer

('ab') is correct because the 'a' mode opens the file for appending, which writes data at the end without truncating the existing content, and adding 'b' specifies binary mode. This allows binary data to be written to a file that already exists without losing its current contents.

Exam trap

Python Institute often tests the distinction between 'w' (truncate) and 'a' (append) modes, trapping candidates who assume 'wb' is the only way to write binary data without considering preservation of existing content.

How to eliminate wrong answers

Option A ('wb') is wrong because 'w' mode truncates the file to zero length upon opening, destroying any existing data. Option B ('rb') is wrong because 'r' mode opens the file for reading only, not writing. Option D ('wb+') is wrong because 'w+' mode also truncates the file upon opening, even though it allows both reading and writing.

66
MCQhard

What is the output of the following code? try: raise ValueError('a') except ValueError as e: print(e.args[0]) finally: print('b')

A.a b
B.b a
C.a\nb
D.b
AnswerC

"a\nb" is the exact output. The raise ValueError in the try block transfers control to the except ValueError handler, whose print('a') writes 'a' plus a newline. After that handler finishes, the finally block unconditionally runs and print('b') writes 'b' plus a newline, yielding two lines: first 'a', second 'b'.

Why this answer

The `finally` block always executes after the `try` block, even when an exception is raised. The `except` block catches the `ValueError` and prints the first argument of the exception (`'a'`), then the `finally` block prints `'b'`. The output is `a` on one line and `b` on the next, matching `a\nb`.

Exam trap

Python Institute often tests the misconception that `finally` runs before `except` or that `print()` outputs on the same line, leading candidates to choose options with incorrect order or missing newlines.

How to eliminate wrong answers

Option A is wrong because it suggests both outputs appear on the same line (`a b`), but `print()` adds a newline by default, so they appear on separate lines. Option B is wrong because it reverses the order to `b a`, but the `finally` block executes after the `except` block, not before. Option D is wrong because it omits the `'a'` output entirely, but the `except` block does execute and prints the exception argument before the `finally` block runs.

67
Multi-Selecteasy

Which TWO of the following are built-in Python exceptions?

Select 2 answers
A.CustomException
B.InputError
C.ValueError
D.FileNotFoundError
E.FileReadError
AnswersC, D

ValueError is a built-in exception in Python, defined in the `builtins` module and raised when a function receives an argument of the correct type but an invalid value—for example, `int('abc')` or `math.sqrt(-1)`. It is deliberately distinct from `TypeError`, which covers type mismatches, allowing programmers to catch value-specific errors cleanly. As a built-in, it is always available without any import and is part of the core exception hierarchy.

Why this answer

ValueError (C) is a built-in Python exception that is raised when a built-in operation or function receives an argument with the correct type but an inappropriate value, such as int('abc'). FileNotFoundError (D) is a built-in exception in Python 3, raised when a file or directory is requested but does not exist, commonly encountered during file I/O operations like open().

Exam trap

Python Institute often tests the distinction between built-in exceptions and user-defined or non-existent exceptions, and the trap here is that candidates may confuse InputError or FileReadError with real built-in exceptions like EOFError or OSError, or assume that any error related to input or files must be a built-in exception.

68
MCQmedium

A developer wants to ensure that a file is always closed, even if an exception occurs, without using the 'with' statement. Which approach correctly achieves this?

A.f = open('file.txt'); try: ... except: ... else: f.close()
B.f = open('file.txt'); try: ... finally: f.close()
C.if f.closed: pass else: f.close()
D.try: f = open('file.txt'); ... except: pass; finally: f.close()
AnswerB

Using `try: ... finally: f.close()` is the canonical Python idiom because the `finally` block is guaranteed to execute whether or not an exception is raised inside the `try` block. Unlike `except`, which only handles exception paths, `finally` runs on normal completion, on exception propagation, and even when a `break`, `continue`, or `return` is encountered in the `try` body. This ensures that the file descriptor is released deterministically, preventing resource leaks in both expected and exceptional control flows. It is the building block of context managers, where the `with` statement uses `__exit__` to achieve similar deterministic cleanup.

Why this answer

The `finally` block is guaranteed to execute regardless of whether an exception occurs in the `try` block. This ensures that `f.close()` is always called, properly releasing the file resource. The `with` statement is not used, but the `try...finally` construct provides the same deterministic cleanup behavior.

Exam trap

Python Institute often tests the distinction between `else` and `finally` in exception handling, trapping candidates who think `else` runs unconditionally or that placing `open()` inside the `try` block is safe without checking for assignment failure.

How to eliminate wrong answers

Option A is wrong because the `else` block only runs if no exception occurs; if an exception is raised, `f.close()` is never executed, leaving the file open. Option C is wrong because it references `f.closed` before `f` is defined in the given code snippet, and even if defined, it does not guarantee closure after an exception — it is a conditional check, not a cleanup mechanism. Option D is wrong because the `except` block contains `pass`, which silently swallows exceptions, and although `finally` runs, the `try` block includes the `f = open(...)` statement; if `open()` itself raises an exception (e.g., file not found), `f` is never assigned, causing a `NameError` in the `finally` block when trying to call `f.close()`.

69
MCQhard

A developer is working on a data pipeline that processes files from untrusted sources. The pipeline should catch and log any exception, but also ensure that sensitive information from the exception (e.g., file paths) is not exposed to end users. Which approach balances security and debugging?

A.Catch the exception and re-raise the same exception.
B.Catch the exception, log it, and suppress it silently.
C.Catch the exception, log the full traceback, then raise a custom generic exception.
D.Catch the exception and print it to the console.
AnswerC

This is the recommended approach because it separates internal diagnostics from user-facing failure information. Logging the full traceback preserves the exact stack, exception types, and local context for developers, while raising a custom generic exception like PipelineProcessingError prevents sensitive implementation details from leaking. Using a custom exception also gives callers a stable interface for retry and alerting logic without coupling them to low-level I/O or network exceptions.

Why this answer

It balances security and debugging: the full traceback is logged for developers (preserving debugging details like file paths), while a custom generic exception is raised to end users, preventing sensitive information from being exposed. This approach follows the principle of least privilege for error handling, ensuring that internal details are not leaked to untrusted sources.

Exam trap

Python Institute often tests the distinction between logging exceptions for debugging versus exposing them to users, and the trap here is that candidates may choose Option A (re-raise) thinking it preserves the exception chain, but they overlook the security requirement to hide sensitive details from end users.

How to eliminate wrong answers

Option A is wrong because re-raising the same exception would expose the original exception's details (including sensitive file paths) to the end user, violating security requirements. Option B is wrong because suppressing the exception silently hides all debugging information from logs, making it impossible for developers to diagnose issues in the pipeline. Option D is wrong because printing the exception to the console exposes sensitive information directly to the user or console output, which is insecure and does not log for debugging.

70
MCQmedium

A programmer wants to catch both `FileNotFoundError` and `PermissionError` with a single except clause. Which tuple is correct?

A.except (FileNotFoundError, PermissionError):
B.except FileNotFoundError, PermissionError:
C.except OSError:
D.except [FileNotFoundError, PermissionError]:
AnswerA

Correct syntax: parentheses form a tuple listing the two exception classes to catch. Python checks the raised exception against each class in the tuple and handles either FileNotFoundError or PermissionError in the same block. Because both derive from OSError, using this tuple is more precise than catching the parent class and avoids masking unrelated OSError subclasses.

Why this answer

Python's exception handling syntax allows a tuple of exception types in a single `except` clause, enabling the programmer to catch multiple exception types with the same handler. Both `FileNotFoundError` and `PermissionError` are subclasses of `OSError`, but using the tuple explicitly catches only those two specific exceptions, not all `OSError` subtypes.

Exam trap

Python Institute often tests the distinction between the correct tuple syntax `except (Exc1, Exc2):` and the incorrect comma-separated syntax `except Exc1, Exc2:` (which is a Python 2 relic), or the overly broad `except OSError:` that catches more than intended.

How to eliminate wrong answers

Option B is wrong because it uses a comma instead of parentheses, which is the old Python 2 syntax for catching exceptions and assigning the exception instance to a variable; in Python 3, this raises a `SyntaxError`. Option C is wrong because while `FileNotFoundError` and `PermissionError` are both subclasses of `OSError`, catching `OSError` would also catch many other unrelated exceptions (e.g., `FileExistsError`, `IsADirectoryError`), which is not what the programmer wants. Option D is wrong because square brackets denote a list, not a tuple; Python's `except` clause requires a tuple of exception types, and using a list will raise a `TypeError`.

71
MCQeasy

A small web application allows users to download files from a server. The code uses open() without any exception handling. When a user requests a non-existent file, the server crashes with a traceback and returns a 500 Internal Server Error to the client. The team needs to modify the code to handle this situation gracefully: if the file does not exist, the application should return a 404 Not Found response (by calling a function send_404()). The application should not catch unrelated exceptions like KeyboardInterrupt. Which modification is the most appropriate?

A.Wrap the entire request handling in a try-except block catching Exception, and if any exception occurs, call send_500().
B.Check if the file exists using os.path.exists before opening, and if not, call send_404().
C.Wrap the open() call in a try-except block catching OSError, and in the except block call send_404().
D.Wrap the open() call in a try-except block catching FileNotFoundError, and in the except block call send_404().
AnswerD

FileNotFoundError is a precise subclass of OSError that Python's open() raises when the requested path cannot be found, including cases where a parent directory is missing or the path is a dangling symlink. By catching only this exception, the handler maps the specific 'missing resource' condition to send_404() and lets every other I/O problem—such as PermissionError—propagate or be handled elsewhere. This follows the EAFP (easier to ask forgiveness than permission) idiom and avoids the broader catch-all problems of checking existence beforehand.

Why this answer

It catches the specific exception raised when a file is not found (FileNotFoundError), which is a subclass of OSError. This allows the code to return a 404 response for missing files while not catching unrelated exceptions like KeyboardInterrupt, as required. The except block calls send_404() to handle the missing file gracefully without crashing the server.

Exam trap

Python Institute often tests the distinction between catching a specific exception (FileNotFoundError) versus its parent class (OSError), and the trap here is that candidates may choose the broader OSError (Option C) thinking it covers all file-related errors, but that would incorrectly handle permission or other OS errors as 404s.

How to eliminate wrong answers

Option A is wrong because it catches all exceptions (including KeyboardInterrupt) and calls send_500(), which does not distinguish between a missing file and other errors, violating the requirement to not catch unrelated exceptions. Option B is wrong because it introduces a race condition: between checking os.path.exists and opening the file, the file could be deleted or renamed, leading to an unhandled exception. Option C is wrong because catching OSError is too broad; it would catch other OS-related errors (e.g., permission denied) and incorrectly return a 404, when the requirement is to only handle non-existent files with a 404 response.

72
MCQhard

A pipeline processes many small binary records. The developer writes a custom exception `class RecordError(Exception)` with an `__init__` that stores a record identifier and calls `super().__init__(message)`. A validation function raises `RecordError` for a corrupt record, and a worker catches it to log the identifier. The worker also wants the raw message to be available via `str(e)`. Which statement about this design is correct?

A.Because RecordError defines its own __init__, the message passed to super().__init__ is discarded and str(e) returns an empty string.
B.The stored record identifier is accessible on the caught instance, and str(e) returns the message because super().__init__ was called with it.
C.The worker must use e.args[0] instead of str(e), because custom exceptions lose the default string representation once they override __init__.
D.The custom exception cannot be caught by except Exception because it does not inherit directly from BaseException.
AnswerB

Assigning the identifier as an attribute in the subclass __init__ makes it available on the caught exception object, which is how the worker logs it. Delegating to Exception.__init__ with the message populates the args tuple, and the inherited __str__ returns that message. Both requirements are satisfied by this design.

Why this answer

A custom exception that stores extra state in __init__ and delegates the message to Exception.__init__ preserves both capabilities: the identifier is available as an attribute on the instance, and the inherited __str__ renders the message from args. Overriding __init__ does not disable __str__, and subclassing Exception keeps the type catchable by broad handlers.

Exam trap

The trap here is believing that a custom __init__ erases the default string representation, when str(e) still works as long as the subclass forwards the message to Exception.__init__.

73
MCQmedium

A developer is implementing a custom exception for invalid data. Which class should the custom exception inherit from?

A.RuntimeError
B.ArithmeticError
C.BaseException
D.Exception
AnswerD

Exception is the standard, recommended base class for custom exceptions because it is the root of the ordinary error hierarchy, below BaseException but above all built-in exceptions meant for program-level failures. Deriving from it ensures your invalid-data exception is caught by generic `except Exception` handlers, supports chaining with `__cause__`, and clearly communicates that it is an application-level error. This is the convention described in Python's official documentation and followed by most libraries and frameworks.

Why this answer

The `Exception` class is the base class for all built-in, non-system-exiting exceptions in Python. Custom exceptions should inherit from `Exception` (or one of its subclasses) to ensure they are caught by generic `except Exception:` handlers and integrate properly with Python's exception hierarchy, while avoiding the system-exiting exceptions derived from `BaseException`.

Exam trap

The trap here is that candidates often choose `BaseException` thinking it is the most general base class, but Cisco tests the understanding that custom exceptions should inherit from `Exception` to avoid accidentally catching system-exiting exceptions like `KeyboardInterrupt`.

How to eliminate wrong answers

Option A is wrong because `RuntimeError` is a specific built-in exception for errors that do not fit into other categories; inheriting from it would misrepresent the custom exception's semantics and is not the recommended base for all custom exceptions. Option B is wrong because `ArithmeticError` is a narrow base for arithmetic-related errors (e.g., ZeroDivisionError); using it for generic invalid data exceptions would be semantically incorrect and overly restrictive. Option C is wrong because `BaseException` is the root of all exceptions, including system-exiting ones like `SystemExit` and `KeyboardInterrupt`; inheriting from it would cause the custom exception to be caught by `except BaseException:` blocks, which is not intended for user-defined exceptions and can suppress critical system signals.

74
MCQeasy

A developer writes a function that reads a configuration file and returns its contents as a string. The file might not exist. Which exception should be caught to handle a missing file?

A.FileNotFoundError
B.PermissionError
C.IOError
D.OSError
AnswerA

FileNotFoundError is a built-in exception raised when a file or directory is requested but cannot be found at the specified path. It is a subclass of OSError and is specifically designed for missing-file scenarios, which is exactly the case when reading a configuration file that does not exist. In Python 3, it is the canonical exception for this situation, replacing the more generic IOError that was used in earlier versions.

Why this answer

`FileNotFoundError` is a built-in exception in Python that is raised when a file or directory is requested but does not exist. In Python 3, file-related I/O errors are organized under `OSError` with specific subclasses, and `FileNotFoundError` is the precise exception for a missing file, making it the most appropriate catch for this scenario.

Exam trap

Python Institute often tests the distinction between the broad `OSError` and its specific subclass `FileNotFoundError`, trapping candidates who think catching the parent class is safer, when in fact the exam expects precise exception handling for a missing file.

How to eliminate wrong answers

Option B is wrong because `PermissionError` is raised when the file exists but the process lacks the required permissions to access it, not when the file is missing. Option C is wrong because `IOError` was an alias for `OSError` in Python 2 but is no longer a separate exception in Python 3; catching it would not specifically target a missing file and is considered deprecated. Option D is wrong because `OSError` is the parent class for all system-related exceptions, including `FileNotFoundError`, but catching the parent is too broad and does not precisely handle the missing file case; it would also catch unrelated OS errors like permission or disk errors.

75
Multi-Selecteasy

Which TWO of the following are correct ways to raise a custom exception in Python? (Assume CustomError and CustomException are user-defined.)

Select 2 answers
A.raise "Custom error"
B.raise 42
C.raise CustomError("invalid")
D.raise Exception
E.raise CustomException()
AnswersC, E

This constructs a new instance of the custom exception class immediately before raising it, passing the string "invalid" into the constructor. That value is stored in the instance's args attribute and can be retrieved in an except block, making it the standard, readable way to raise a user-defined exception with diagnostic detail.

Why this answer

It raises a user-defined exception by instantiating the custom exception class `CustomError` with an argument (the string "invalid"). In Python, the `raise` statement must be followed by an exception instance or an exception class; `CustomError("invalid")` creates an instance of the custom exception, which is the proper way to raise a custom exception with a custom message.

Exam trap

Python Institute often tests the distinction between raising an exception class versus an exception instance, and the fact that only instances (or classes that are subclasses of `BaseException`) are valid arguments to `raise` — candidates mistakenly think any object can be raised or that raising a class without instantiation is the only correct way.

Page 1 of 2 · 76 questions totalNext →

Ready to test yourself?

Try a timed practice session using only Exceptions and File I/O questions.