Courseiva

CCNA Library Modules Questions

48 questions · Library Modules topic · All types, answers revealed

1
MCQhard

You are using the logging module in a long-running service. You need to ensure that a specific logger named 'app.db' writes DEBUG and higher messages to a file, but its parent logger 'app' must not propagate these DEBUG messages to the root logger. Which configuration achieves this?

A.Set the 'app.db' logger level to DEBUG, add a FileHandler, and set the root logger level to INFO.
B.Set the 'app.db' logger level to DEBUG, add a FileHandler, and set 'app.db'.propagate = False.
C.Set the 'app' logger level to DEBUG, add a FileHandler to 'app.db', and leave propagate at its default.
D.Set the 'app.db' logger level to DEBUG, add a FileHandler, and add a NullHandler to the 'app' logger.
AnswerB

Setting the logger level to DEBUG allows DEBUG and higher messages to be processed. Adding a FileHandler directs them to a file. Setting propagate to False prevents the logger from passing records to its parent 'app' and ultimately the root logger, so DEBUG messages do not reach other handlers. This exactly meets the requirement without affecting other loggers.

Why this answer

To keep DEBUG messages from 'app.db' confined to its own FileHandler, the logger must process DEBUG records and must not propagate them to ancestors. Setting the logger level to DEBUG enables processing, adding a FileHandler writes to the file, and setting propagate to False stops upward propagation. Other options either allow propagation or attempt to control it via unrelated levels or handlers, which does not achieve the isolation.

Exam trap

The trap here is thinking that setting the root logger level or adding a NullHandler to a parent will suppress propagated records, when propagation bypasses level checks and NullHandler only discards records after they have already been passed upward.

2
MCQeasy

What is the purpose of the logging.StreamHandler?

A.To write logs to a file.
B.To send logs to a stream like stdout.
C.To format log messages.
D.To rotate log files.
AnswerB

StreamHandler writes formatted log records to any file-like stream object, defaulting to sys.stderr but commonly pointed at sys.stdout. It satisfies the stem's requirement of directing log output to a stream, unlike FileHandler, which always opens a named file on disk.

Why this answer

It sends log messages to a stream, such as sys.stderr or sys.stdout.

3
MCQmedium

You are developing a Python application that must parse a large XML file and extract specific data. The file is too large to fit into memory, so you need to process it incrementally. Which approach using the xml.etree.ElementTree module is most appropriate?

A.Use xml.etree.ElementTree.fromstring() to parse the file in chunks by reading it line by line and passing each line to fromstring().
B.Use xml.etree.ElementTree.parse() to load the entire file into memory and then iterate over the elements.
C.Use xml.etree.ElementTree.XMLParser() with a custom target to build the tree incrementally, then process the tree.
D.Use xml.etree.ElementTree.iterparse() to iterate over the file and process elements as they are parsed, clearing them from memory afterwards.
AnswerD

iterparse() provides an incremental parser that yields events for start and end of elements. By processing elements and then clearing them using element.clear() or removing them from the root, you can keep memory usage low. This is the recommended approach for large XML files. It allows you to handle data as it is parsed without loading the entire document into memory.

Why this answer

iterparse() is designed for incremental parsing of large XML files. It generates events as it parses, allowing you to process elements and then clear them to free memory. This keeps memory usage bounded and is the standard way to handle large XML with ElementTree.

The other options either load the entire file into memory or are not suited for incremental parsing.

Exam trap

The trap here is confusing iterparse() with other parsing methods like parse() or fromstring(); iterparse() is the only one that supports incremental, memory-efficient parsing.

4
MCQeasy

When using configparser, how do you retrieve a value as a boolean?

A.parser.get('section', 'option', type=bool)
B.parser.get_bool('section', 'option')
C.parser.getboolean('section', 'option')
D.bool(parser.get('section', 'option'))
AnswerC

getboolean applies configparser's boolean conversion, accepting values such as 'yes', 'no', 'true', 'false', 'on', 'off' and '1'/'0', and raising ValueError for anything else. get() would return the raw string, leaving type conversion to your own code.

Why this answer

The getboolean() method converts common truthy/falsy values automatically.

5
MCQhard

You are using the `json` module to serialize a custom object that contains a `datetime.date` attribute. When you call `json.dumps(obj)`, you get a `TypeError: Object of type date is not JSON serializable`. Which approach correctly allows serialization while preserving the date as an ISO 8601 string?

A.Create a subclass of `json.JSONEncoder` and override its `default` method to return `obj.isoformat()` for `date` instances, then pass it to `json.dumps` via the `cls` parameter.
B.Implement a `__json__` method on the custom object that returns a serializable dictionary, and `json.dumps` will call it automatically.
C.Use `json.dumps(obj, default=str)` to automatically convert any non-serializable object to its string representation.
D.Convert the `date` attribute to a string using `obj.date.isoformat()` before calling `json.dumps`, and then convert it back when deserializing.
AnswerA

The `json` module allows customization through a `JSONEncoder` subclass. Overriding the `default` method lets you define how to serialize unsupported types like `date`. Returning `obj.isoformat()` produces an ISO 8601 string. Passing the class via `cls` to `json.dumps` instructs the encoder to use it. This is the standard, extensible solution.

Why this answer

The `json` module's `JSONEncoder` class provides a `default` method that is called for objects that are not natively serializable. By subclassing and overriding this method, you can return a serializable representation, such as an ISO 8601 string for dates. Passing this encoder class to `json.dumps` via the `cls` argument enables the custom behavior.

Exam trap

The trap here is assuming that the `json` module has built-in support for `datetime` objects or that a special method like `__json__` is automatically invoked, when in fact you must explicitly provide a custom encoder or default function.

6
MCQeasy

You are writing a script that reads a large CSV file using csv.reader. The file uses a semicolon as the delimiter and contains quoted fields with embedded newlines. Which instantiation correctly handles this format?

A.csv.reader(file, delimiter=';', quoting=csv.QUOTE_NONE)
B.csv.reader(file, delimiter=';', quotechar='"')
C.csv.reader(file, delimiter=',', quotechar='"')
D.csv.reader(file, delimiter=';', escapechar='\\')
AnswerB

The csv.reader accepts delimiter and quotechar parameters. Setting delimiter to ';' matches the file's separator, and quotechar to '"' allows proper parsing of quoted fields, including those containing embedded newlines. This is the correct and sufficient configuration for the described format.

Why this answer

The csv.reader requires the correct delimiter and quotechar to parse a file with semicolon-separated values and quoted fields containing newlines. Setting delimiter to ';' and quotechar to '"' ensures that embedded newlines within quotes are treated as part of the field. Disabling quoting or using the wrong delimiter breaks parsing, and an escapechar alone does not address quoted newlines.

Exam trap

The trap here is assuming that an escapechar or quoting mode can replace the quotechar for handling embedded newlines, when in fact the quotechar is essential for the csv module to recognize quoted fields.

7
MCQmedium

You are writing a Python application that must parse a configuration file where a value spans multiple lines, such as a long list of email addresses separated by newlines. You decide to use the configparser module. Which of the following correctly describes how to include a multi-line value in the configuration file?

A.Indent continuation lines with whitespace; they will be joined with newline characters.
B.Separate lines with a semicolon to indicate continuation.
C.Enclose the value in triple quotes to allow multiple lines.
D.Use a backslash at the end of each line to indicate continuation.
AnswerA

In configparser, multi-line values are created by indenting subsequent lines. The parser joins these lines with newline characters, preserving them as part of the value. This allows you to store lists or long strings without additional escaping. The indentation must be consistent and deeper than the key's indentation. This behavior is documented and widely used for configuration files like setup.cfg.

Why this answer

In configparser, multi-line values are specified by indenting continuation lines. The parser then joins these lines with newline characters. This is the standard way to include values that span multiple lines, such as lists.

The other options incorrectly suggest backslashes, triple quotes, or semicolons, which are not part of the INI format syntax for continuation.

Exam trap

The trap here is assuming that Python-like line continuation (backslash) or string literal syntax (triple quotes) applies to configparser files.

8
MCQhard

You are logging events with custom levels. How do you add a custom level 'TRACE' (value 5) to the logging module?

A.logging.TRACE = 5
B.logging.setLevel('TRACE', 5)
C.logging.addLevelName(5, 'TRACE')
D.logging.define_level('TRACE', 5)
AnswerC

logging.addLevelName() registers a numeric level with its name in the module's internal name-to-level mapping, so records logged at 5 render as 'TRACE'. This is the documented API for introducing custom levels without subclassing or patching internals.

Why this answer

You use logging.addLevelName() to associate a numerical value with a level name.

9
MCQeasy

In the context of the CSV module, what is a 'dialect'?

A.A specific file extension.
B.A set of parameters defining a CSV format.
C.The encoding of the file.
D.A list of column names.
AnswerB

A dialect groups formatting parameters — delimiter, quotechar, quoting, line terminator, escapechar — that together describe one CSV variant. Passing a dialect to reader or writer applies that whole parameter set, which is exactly the definition the stem requests.

Why this answer

A dialect is a grouping of parameters (delimiter, quotechar, etc.) that defines the format of a CSV file.

10
MCQhard

You are working with a large XML file and need to extract specific elements efficiently without loading the entire document into memory. You decide to use the xml.etree.ElementTree module. Which of the following methods should you use to iterate over all 'book' elements in the document?

A.Use the findall() method on the root element to retrieve all 'book' elements at once.
B.Use the XMLPullParser to pull events and process 'book' elements as they are encountered.
C.Use the iterparse() function to process the XML incrementally and handle 'end' events for 'book' tags.
D.Use the parse() function and then iterate over the tree using a for loop.
AnswerC

iterparse() is designed for incremental parsing of large XML files. It generates events (start, end, start-ns, end-ns) and allows you to process elements as they are parsed. By listening for 'end' events and checking if the tag is 'book', you can extract each book element and then clear it to free memory. This is the most memory-efficient way to handle large files.

Why this answer

For memory-efficient parsing of large XML files, iterparse() is the recommended function. It allows incremental processing by generating events as elements are parsed. By handling 'end' events for 'book' tags and clearing elements, you can extract data without loading the entire document.

The other methods load the full document into memory, which is inefficient for large files.

Exam trap

The trap here is assuming that findall() or parse() are memory-efficient because they are commonly used, but they load the entire XML tree into memory.

11
MCQmedium

When using configparser, what happens if you attempt to read a configuration file that does not exist using the read() method?

A.It raises a FileNotFoundError.
B.It raises a configparser.Error.
C.It creates an empty configuration object.
D.It returns an empty list.
AnswerD

`read()` returns a list of filenames successfully parsed, so a missing file simply yields an empty list rather than raising an exception. This satisfies the stem's scenario because `configparser` deliberately treats absent files as non-fatal, letting callers supply defaults or fallback paths without wrapping the call in error handling.

Why this answer

The read() method returns an empty list and does not raise an exception.

12
MCQmedium

You are writing a Python script that must process a large text file line by line. The file is UTF-8 encoded, but some lines contain characters that are not representable in the default system encoding. You want to ensure that the script reads the file correctly on any platform. Which code correctly opens the file?

A.open('data.txt', 'r')
B.open('data.txt', 'r', errors='ignore')
C.open('data.txt', 'rb')
D.open('data.txt', 'r', encoding='utf-8')
AnswerD

Explicitly specifying `encoding='utf-8'` ensures that the file is decoded using UTF-8 regardless of the platform's default encoding. This is the recommended practice for text files to avoid `UnicodeDecodeError` on systems where the default encoding is not UTF-8, such as Windows with cp1252.

Why this answer

Specifying `encoding='utf-8'` when opening a text file ensures consistent decoding across platforms. Relying on the default encoding can cause errors on systems where the default is not UTF-8. The `errors` parameter should not be used to mask decoding issues when the goal is correct reading.

Exam trap

The trap here is assuming that the default encoding is always UTF-8, or that using `errors='ignore'` is a safe way to handle encoding issues, when in fact it can hide data corruption.

13
Multi-Selectmedium

Which TWO of the following are valid ways to define a configuration option in configparser?

Select 2 answers
A.parser['section']['option'] = 'value'
B.parser.add_option('section', 'option', 'value')
C.parser.write('section', 'option', 'value')
D.parser.set('section', 'option', 'value')
E.parser.insert('section', 'option', 'value')
AnswersA, D

Assigning through `parser['section']['option'] = 'value'` works because `ConfigParser` implements the mapping protocol: `__getitem__` returns a `SectionProxy` that supports `__setitem__`, writing straight into the section. This satisfies the stem's requirement for a valid definition method, unlike `set()` or `add_option()`, which do not exist on the parser.

Why this answer

Option A is correct because configparser supports the mapping-style interface, so assigning parser['section']['option'] = 'value' creates or updates the option 'option' in 'section' with the string 'value'. Option D is correct because the ConfigParser.set(section, option, value) method is the explicit API for setting an option's value within a section, and it requires the section to already exist. Options B, C, and E are not valid configparser methods: add_option, write, and insert do not exist with those signatures — write() actually writes the configuration to a file-like object, and there is no add_option or insert method for defining options.

14
MCQmedium

You are writing to a CSV file. If your data contains the delimiter character itself (e.g., a comma in a text field), what does the csv module do by default?

A.It raises a csv.Error.
B.It quotes the field.
C.It ignores the delimiter.
D.It escapes the character with a backslash.
AnswerB

The csv writer applies QUOTE_MINIMAL by default, wrapping any field containing the delimiter, quotechar or newline in double quotes and escaping embedded quotes by doubling them. This preserves the comma inside the text field so the reader parses it as one value rather than splitting it.

Why this answer

The csv module automatically wraps such fields in quotes.

15
Multi-Selectmedium

You are using the csv module to read a file that contains fields with embedded newlines and commas. Which TWO of the following statements about the csv.reader are correct? (Choose two.)

Select 2 answers
A.The csv.reader requires the file to be opened with newline='' to correctly handle embedded newlines.
B.The csv.reader can only read files encoded in UTF-8.
C.The csv.reader returns each row as a list of strings, regardless of the original data types.
D.The csv.reader automatically converts numeric fields to int or float.
E.The csv.reader automatically detects and uses the correct delimiter based on the file content.
AnswersA, C

When reading CSV files with embedded newlines, you must open the file with newline='' to prevent universal newline translation from interfering. The csv module expects the file to be opened with newline='' so it can correctly interpret line breaks within quoted fields. This is a documented requirement for both reading and writing.

Why this answer

The csv.reader requires newline='' when opening the file to handle embedded newlines correctly, and it always returns rows as lists of strings. It does not auto-detect delimiters or convert types, and it supports any encoding. These behaviors are essential for correct CSV parsing.

Exam trap

The trap here is assuming csv.reader performs smart parsing like delimiter detection or type conversion, when it is deliberately simple.

16
MCQeasy

When parsing XML with ElementTree, how do you retrieve the text content of an element?

A.element.content
B.element.value
C.element.get_text()
D.element.text
AnswerD

ElementTree stores an element's direct text in its .text attribute, which returns the string between the opening and closing tags (or None if empty). This is the standard accessor for retrieving character data from a parsed element, satisfying the requirement to obtain text content.

Why this answer

The .text attribute of the Element object holds the text content.

17
Multi-Selectmedium

You are building a Python application that uses the shelve module to store persistent data. You want to ensure that the database file is updated correctly and that you can access keys as attributes. Which TWO of the following statements about the shelve module are true? (Choose two.)

Select 2 answers
A.By default, shelve uses the pickle module to serialize values.
B.The shelve module provides a dictionary-like interface for persistent storage.
C.shelve automatically synchronizes changes to disk after every assignment.
D.You can access shelf keys as attributes using dot notation.
E.The shelve module is thread-safe by default.
AnswersA, B

shelve uses pickle by default to serialize values before storing them in the underlying dbm database. This allows storage of arbitrary Python objects, as long as they are picklable. The keys are also pickled. This is a fundamental aspect of how shelve works. The statement is true and important to understand for correct usage, especially regarding object compatibility across Python versions.

Why this answer

The shelve module provides a persistent, dictionary-like object. It uses pickle to serialize values by default, allowing storage of complex Python objects. However, it does not automatically sync after each assignment; you must call sync() or close the shelf.

Keys are accessed via subscription, not attributes, and it is not thread-safe. Therefore, the true statements are about the dictionary-like interface and pickle serialization.

Exam trap

The trap here is assuming that shelve automatically saves changes immediately or that it supports attribute access, which it does not.

18
MCQmedium

A colleague's script parses a CSV export that uses a semicolon as the field separator and contains quoted text fields with embedded semicolons. They call csv.reader(f) without arguments and complain that rows are split incorrectly into too many fields. What is the correct fix?

A.Pre-process each line with str.split(';') before feeding the rows to csv.reader().
B.Open the file with newline='' and pass delimiter=';' to csv.reader().
C.Pass dialect='excel-tab' to csv.reader() to switch to tab-separated parsing.
D.Pass quoting=csv.QUOTE_NONE to csv.reader() so embedded semicolons are ignored.
AnswerB

csv.reader() defaults to a comma delimiter, so semicolon-separated data splits at every semicolon, including those inside quoted fields once quoting rules do not match. Supplying delimiter=';' makes the parser treat semicolons as separators and honour the default quotechar so embedded semicolons inside quotes stay within one field. Opening with newline='' is also required so the csv module controls line splitting.

Why this answer

The csv module defaults to a comma delimiter, so a semicolon-separated file must be parsed with delimiter=';'. Because quoted fields may contain the delimiter, that quoting behaviour must be preserved, which is the default when quotechar is left unchanged. The file should also be opened with newline='' so that embedded line breaks inside quoted fields are handled by the csv parser rather than by universal newline translation.

Exam trap

The trap here is assuming csv.reader() auto-detects delimiters, when it always defaults to a comma unless told otherwise.

19
Multi-Selectmedium

Which THREE of the following are valid parameters for the csv.writer constructor?

Select 3 answers
A.lineterminator
B.encoding
C.buffer_size
D.quotechar
E.delimiter
AnswersA, D, E

`lineterminator` is a valid `csv.writer` constructor parameter, letting you override the default `'\r\n'` row separator when writing files. This satisfies the stem's requirement for genuine constructor arguments, unlike dialect-only or reader-specific settings. It directly controls the character sequence terminating each written row.

Why this answer

The csv.writer constructor accepts a dialect and formatting parameters, and lineterminator (A) is a valid parameter that sets the string used to terminate lines written by the writer, defaulting to '\r\n'. quotechar (D) is also valid and specifies the single character used to quote fields containing special characters such as the delimiter or quotechar itself. delimiter (E) is valid as well, defining the one-character string used to separate fields, defaulting to a comma. The encoding (B) option is not a csv.writer parameter; encoding is handled by the underlying file object passed to the writer, typically via open(). The buffer_size (C) option is likewise not a csv.writer parameter; buffering is controlled by the file object's buffering argument in open(), not by the CSV writer.

20
MCQeasy

You are writing a Python script that must read a configuration file in TOML format. Which module from the Python Standard Library should you use?

A.yaml
B.configparser
C.tomllib
AnswerC

tomllib is the standard library module introduced in Python 3.11 for parsing TOML files. It provides load() and loads() functions to read TOML data into Python dictionaries. For older Python versions, you would need a third-party library, but for current Python, tomllib is the correct standard module.

Why this answer

tomllib is the Standard Library module for reading TOML files, added in Python 3.11. It correctly parses TOML syntax and returns native Python types. Other modules like configparser, json, or yaml are either for different formats or not in the standard library.

Exam trap

The trap here is assuming configparser can handle any configuration format, including TOML.

21
Multi-Selectmedium

You are working with the sqlite3 module to build a small inventory application. You need to execute a parameterized INSERT statement and then retrieve the auto-generated primary key for the newly inserted row. Which two approaches are valid and safe? (Choose two.)

Select 2 answers
A.Execute the INSERT with placeholders, then query the sqlite_sequence table for the maximum value.
B.Execute the INSERT with placeholders, then call cursor.lastrowid.
C.Execute the INSERT with string formatting, then call connection.insert_id().
D.Execute the INSERT with placeholders, then execute SELECT last_insert_rowid().
E.Execute the INSERT with placeholders, then call cursor.fetchone() to get the new primary key.
AnswersB, D

cursor.lastrowid returns the rowid of the most recent successful INSERT on that cursor. For a table with an INTEGER PRIMARY KEY, this is the auto-generated key. Using placeholders for parameters prevents SQL injection. This is a standard, safe method to obtain the new key immediately after insertion.

Why this answer

The two safe and valid ways to retrieve the auto-generated primary key after an INSERT are cursor.lastrowid and the SQL function last_insert_rowid(). Both operate on the same connection and return the rowid of the most recent successful INSERT. The other options either use non-existent APIs, insecure string formatting, or attempt to read a result set that an INSERT does not produce.

Exam trap

The trap here is assuming that fetchone() can return the new key after an INSERT, or that connection.insert_id() exists, when in fact INSERT statements yield no result set and that method is not part of the sqlite3 API.

22
MCQhard

You are writing a reusable module that must expose only a small public API while keeping several helper functions and constants internal. Users of the module should not import the helpers with 'from mymodule import *', but direct access such as mymodule._helper() may still be needed for tests. Which approach fits best?

A.Rename every helper with a leading underscore and omit __all__ entirely.
B.Define __all__ listing only the public names and leave helper names unchanged.
C.Place the helpers in a nested class and expose them as static methods of that class.
D.Rename every helper with a leading underscore and define __all__ listing only the public names.
AnswerD

A leading underscore signals that a name is non-public, and defining __all__ controls exactly which names 'from mymodule import *' brings in, so helpers stay out of star imports while remaining directly accessible for tests. This combination is the documented convention for shaping a module's public surface without hiding implementation entirely. It satisfies both the API restriction and the testing requirement.

Why this answer

Marking implementation details with a leading underscore communicates that they are non-public, while __all__ explicitly defines which names a star import exports. Because __all__ only affects star imports, the underscored helpers remain directly accessible as attributes for unit tests. This pairing gives a precise, documented public API without making the internals unreachable.

Exam trap

The trap here is believing that __all__ makes names private, when it only filters what a star import copies into the caller's namespace.

23
MCQeasy

You are writing a Python script that needs to create a temporary directory, write several files into it, and ensure that the directory and its contents are automatically deleted when the script exits, even if an exception occurs. Which approach using the tempfile module is most appropriate?

A.Use tempfile.gettempdir() to obtain the system temporary directory and create a subdirectory there, relying on the operating system to clean it up.
B.Use tempfile.mkdtemp() to create the directory and manually delete it in a finally block.
C.Use tempfile.TemporaryDirectory() as a context manager; the directory and its contents are removed when the context exits.
D.Use tempfile.NamedTemporaryFile(delete=True) to create a file, and write all other files into the same directory as that file.
AnswerC

tempfile.TemporaryDirectory() creates a temporary directory and returns an object that can be used as a context manager. Upon exiting the with block, the directory and all its contents are recursively deleted, even if an exception is raised inside the block. This provides automatic, exception-safe cleanup and is the idiomatic solution for the scenario.

Why this answer

The TemporaryDirectory class is specifically designed for this use case. It creates a temporary directory and ensures its complete removal when the context manager exits, regardless of whether an exception occurred. This is the most robust and Pythonic way to handle temporary directories with automatic cleanup, avoiding manual cleanup code and potential resource leaks.

Exam trap

The trap here is confusing mkdtemp with TemporaryDirectory; mkdtemp requires manual cleanup, while TemporaryDirectory handles it automatically via the context manager protocol.

24
MCQmedium

You are using configparser and want to access a value that might not exist, but provide a default value if it is missing. Which method is most appropriate?

A.parser.get('section', 'option', fallback='val')
B.parser.get('section', 'option', default='val')
C.parser.get_or_default('section', 'option', 'val')
D.parser.exists('section', 'option') ? ...
E.parser.get('section', 'option') or 'val'
AnswerA

get() accepts a fallback keyword argument, returning that value instead of raising NoOptionError or NoSectionError when the option or section is absent. This directly satisfies the requirement for a default when the value might not exist.

Why this answer

The get() method accepts a 'fallback' argument to return a default value if the option is missing.

25
MCQmedium

When executing a SQL query with parameters in sqlite3, why should you use placeholders (e.g., ?) rather than f-strings?

A.It is required for SELECT queries only.
B.It enables automatic commit behavior.
C.It is faster to execute.
D.It prevents SQL injection vulnerabilities.
AnswerD

Placeholders send parameter values separately from the SQL text, so sqlite3 treats them purely as data rather than executable syntax. This neutralises SQL injection, satisfying the stem's security constraint: f-strings interpolate untrusted input directly into the statement, letting crafted values alter query structure.

Why this answer

Using placeholders prevents SQL injection attacks and allows the library to handle type conversions.

26
MCQhard

You are using the datetime module to calculate the difference between two dates. You have two datetime objects, start and end, and you need to find the number of full days between them, ignoring any fractional part. Which expression correctly computes this?

A.(end - start).microseconds / 86400000000
B.(end - start).total_seconds() / 86400
C.(end - start).seconds / 86400
D.(end - start).days
AnswerD

Subtracting two datetime objects yields a timedelta object. The .days attribute of a timedelta gives the number of whole days (the integer part) between the two dates, discarding any partial day. This directly provides the number of full days.

Why this answer

Subtracting two datetime objects produces a timedelta object. The .days attribute of a timedelta gives the number of full days between the two dates, as an integer, discarding any partial day. This is the correct way to get the number of whole days.

Other attributes like .seconds and .microseconds represent only the respective components, not the total duration.

Exam trap

The trap here is confusing the .days attribute with total_seconds() or other components, or assuming that .seconds gives total seconds instead of the seconds component.

27
MCQhard

You are using the sqlite3 module to insert a large number of rows into a table. You want to maximize performance by reducing the number of disk writes. Which approach is most effective?

A.Set connection.isolation_level = None and execute each INSERT individually.
B.Use a single transaction by executing BEGIN, then many INSERTs, then COMMIT.
C.Set the connection's isolation_level to 'DEFERRED' and commit after every insert.
D.Create a new cursor for each INSERT statement.
AnswerB

Wrapping many INSERT statements in one transaction reduces the number of fsync operations and disk writes. SQLite commits all changes at once when COMMIT is issued. This is the standard way to speed up bulk inserts. The sqlite3 module allows explicit transaction control via BEGIN/COMMIT or by leaving isolation_level at its default and calling commit() once.

Why this answer

Batching many INSERTs into a single transaction minimizes disk I/O and is the most effective way to speed up bulk inserts in sqlite3. Autocommit or frequent commits increase overhead. Using a single cursor also helps, but the transaction grouping is the key factor.

Exam trap

The trap here is thinking that autocommit mode or frequent commits improve performance, when they actually increase disk writes.

28
Multi-Selecthard

Which THREE of the following are valid methods of the xml.etree.ElementTree.Element class?

Select 3 answers
A.find()
B.write()
C.append()
D.set()
E.to_string()
AnswersA, C, D

find() traverses direct child elements matching a tag or path, returning the first match or None. It is a genuine Element method, satisfying the question's requirement for valid Element class methods alongside append() and set().

Why this answer

The xml.etree.ElementTree.Element class provides find(), append(), and set() as valid instance methods. find(match) searches the element's direct children for the first subelement matching the tag or path and returns it (or None), which is a core Element API method. append(subelement) adds a child Element to the end of the element's list of children, and set(key, value) sets an attribute on the element, both being standard Element methods. write() is not an Element method; it belongs to the ElementTree class (ElementTree.write(file, encoding, xml_declaration, ...)), which serializes the whole tree to a file. to_string() is also not an Element method; serialization to a string is done via xml.etree.ElementTree.tostring(element) (no underscore), so option E is invalid.

29
MCQmedium

You are using the sqlite3 module to manage a database. You need to ensure that database changes are permanently saved even if your script terminates unexpectedly. Which method should you call after an INSERT operation?

A.connection.save()
B.cursor.flush()
C.connection.close()
D.connection.commit()
AnswerD

Calling connection.commit() writes the pending transaction to disk, making the INSERT durable. SQLite wraps changes in an implicit transaction, so without commit they are rolled back when the script terminates unexpectedly. This directly satisfies the stem's requirement that changes be permanently saved despite abnormal termination.

Why this answer

The commit() method on a connection object is required to save changes permanently in sqlite3.

30
Multi-Selecteasy

Which TWO of the following are valid ways to create a connection in the sqlite3 module?

Select 2 answers
A.sqlite3.connect(':memory:')
B.sqlite3.Connection('my_db.sqlite')
C.sqlite3.connect('my_db.sqlite')
D.sqlite3.new_db('my_db.sqlite')
E.sqlite3.open('my_db.sqlite')
AnswersA, C

Passing `':memory:'` to `sqlite3.connect()` opens a private, temporary database held entirely in RAM, satisfying the scenario's requirement for an in-memory connection. No file is created on disk, and the database vanishes when the connection closes. This is a documented, valid connection string accepted by the sqlite3 module.

Why this answer

Option A, sqlite3.connect(':memory:'), is correct because sqlite3.connect() is the module's factory function for creating a Connection object, and passing the special filename ':memory:' opens a temporary in-memory database. Option C, sqlite3.connect('my_db.sqlite'), is also correct because the same sqlite3.connect() function accepts a filesystem path and returns a Connection to that database file, creating it if it does not exist. The other options are invalid: sqlite3.Connection is the class of connection objects and is not normally instantiated directly with a filename, while sqlite3.new_db and sqlite3.open are not functions provided by the sqlite3 module.

31
MCQmedium

In the csv module, how do you specify that the CSV file uses a semicolon (;) as a delimiter?

A.csv.reader(f, char=';')
B.csv.reader(f, sep=';')
C.csv.reader(f, quotechar=';')
D.csv.reader(f, delimiter=';')
AnswerD

Passing delimiter=';' to csv.reader overrides the default comma, so the parser splits each row on semicolons instead. This directly satisfies the stem's requirement for a semicolon-separated file, since the delimiter argument defines the field separator character.

Why this answer

The delimiter parameter in the csv.reader or csv.writer function is used for this purpose.

32
MCQmedium

Which method in the xml.dom.minidom module is used to retrieve the value of a specific attribute of an element?

A.element.attr('attr_name')
B.element.getAttribute('attr_name')
C.element.getAttributeNode('attr_name').value
D.element.value('attr_name')
E.element['attr_name']
AnswerB

getAttribute() reads a named attribute's value directly from an Element node, returning a string or empty string if absent. It satisfies the stem's requirement to retrieve one specific attribute by name, unlike attributes or childNodes, which expose whole collections rather than a single value.

Why this answer

The getAttribute() method is used to retrieve the value of an attribute by its name.

33
MCQmedium

You want to execute multiple SQL statements at once in sqlite3. Which method should you use?

A.cursor.executescript()
B.connection.execute_all()
C.cursor.execute_script()
D.cursor.execute_many()
AnswerA

`executescript()` passes the entire SQL string to SQLite's `sqlite3_exec`, which parses and runs each semicolon-separated statement sequentially, satisfying the requirement to execute multiple statements in one call. Unlike `execute()`, which rejects trailing statements after the first, it commits pending transactions beforehand.

Why this answer

The executescript() method allows executing multiple SQL statements separated by semicolons.

34
Multi-Selecthard

You are writing a Python utility that copies a directory tree to a network share using shutil. You must preserve file metadata and fail loudly if the destination already contains a conflicting file, rather than silently overwriting it. Which TWO shutil features satisfy these requirements? (Choose two.)

Select 2 answers
A.Pass copy_function=shutil.copyfile to shutil.copytree() so existing files are never overwritten.
B.Pass dirs_exist_ok=True to shutil.copytree() so the copy proceeds when the destination directory already exists.
C.Pass copy_function=shutil.copy to shutil.copytree() so only permission bits are carried over.
D.Leave the default behaviour of shutil.copytree() unchanged so that a pre-existing destination path raises FileExistsError.
E.Pass copy_function=shutil.copy2 to shutil.copytree() so metadata such as modification times is preserved.
AnswersD, E

By default copytree() has dirs_exist_ok=False, so if the destination directory already exists it raises FileExistsError before copying anything. That is exactly the fail-loudly behaviour requested when the target share already contains the tree. Combined with a copy_function that preserves metadata, the default conflict handling satisfies the requirement without extra code.

Why this answer

Preserving metadata requires a copy function built on copystat, which copy2 provides, and copytree() exposes this through copy_function. Failing loudly on a pre-existing destination is the default copytree() behaviour, since dirs_exist_ok is False unless explicitly set. Together, copy_function=shutil.copy2 and the default dirs_exist_ok value satisfy both stated requirements.

Exam trap

The trap here is assuming that dirs_exist_ok=True is needed to make copytree() work at all, when it actually suppresses the very error the scenario wants.

35
MCQmedium

You are building a desktop tool with tkinter. A user clicks a button, and while a long file-compression routine runs you want a small window with a progress bar to stay visible and animated; the main application window must remain responsive to the user's clicks throughout. Which approach should you use?

A.Instantiate a second Tk() root, place the progress bar in it, and call its mainloop() from the callback.
B.Run the compression loop inside the button's command callback and call update_idletasks() after each chunk is processed.
C.Create a tkinter.Toplevel window for the progress bar and run the compression in a separate thread that posts status updates back to the main thread.
D.Call mainloop() a second time from inside the button's command callback so the progress window gets its own event loop.
AnswerC

Tkinter is not thread-safe, but separating the CPU-bound work onto a worker thread keeps the main thread free to service the event loop, so both windows stay responsive and the progress bar animates. The worker must not touch widgets directly; it should hand results to the main thread, for example through a queue polled with after(), which is the standard pattern for this scenario.

Why this answer

Long-running work must never execute on the thread that runs the Tk event loop. Moving the compression onto a worker thread lets the main thread keep dispatching events, so the progress window redraws and the primary window accepts clicks. Because Tkinter widgets may only be touched from the main thread, the worker communicates through a thread-safe queue that the GUI polls periodically.

Exam trap

The trap here is assuming that sprinkling update_idletasks() or update() into a blocking callback makes tkinter multithreaded or keeps the interface live.

36
MCQhard

You are building a Python script that needs to create a ZIP archive containing files from a directory. You want to preserve the directory structure inside the archive. Which approach using the zipfile module correctly adds the file '/data/reports/summary.txt' as 'reports/summary.txt' inside the archive?

A.zipf.write('/data/reports/summary.txt')
B.zipf.add('/data/reports/summary.txt', 'reports/summary.txt')
C.zipf.write('/data/reports/summary.txt', arcname='summary.txt')
D.zipf.write('/data/reports/summary.txt', arcname='reports/summary.txt')
AnswerD

The write() method's arcname parameter sets the name inside the archive. By passing 'reports/summary.txt', the file is stored with that path, preserving the desired directory structure. This is the correct way to include a file from a different absolute path while renaming it within the archive.

Why this answer

The zipfile.ZipFile.write() method accepts an arcname parameter that specifies the name of the file inside the archive. To preserve a directory structure, you provide a relative path as the arcname, such as 'reports/summary.txt'. This ensures the file is stored with that exact path, regardless of its location on the filesystem.

Exam trap

The trap here is confusing the write() method's arcname parameter with the source filename, or assuming that the source path is automatically mirrored in the archive.

37
MCQhard

When using configparser, how do you handle multiline values?

A.Use a backslash at the end of each line.
B.Indent the subsequent lines.
C.Wrap them in triple quotes ('''...''').
D.Use the '\n' escape character.
AnswerB

ConfigParser treats indented continuation lines as part of the preceding option's value, joining them into one multiline string. Indenting subsequent lines therefore satisfies the stem's requirement, unlike blank lines or unindented text which start new keys.

Why this answer

You indent lines following the initial line within the option.

38
MCQeasy

When using sqlite3.Row, what is the primary benefit over using a standard tuple?

A.It automatically commits transactions.
B.It provides dictionary-like access to columns by name.
C.It is faster to execute.
D.It supports multi-threading natively.
AnswerB

sqlite3.Row wraps each result row so columns are addressable by name as well as index, unlike a plain tuple which only supports positional access. This satisfies the stem by removing the need to remember column order when reading query results.

Why this answer

sqlite3.Row allows accessing column values by name (string keys) instead of just numerical indices.

39
MCQmedium

You are configuring a logging FileHandler. What does the 'mode' parameter control?

A.The log format.
B.The rotation interval.
C.The file opening mode.
D.The character encoding.
AnswerC

The mode parameter is passed straight to the built-in open() call, so it sets the file opening mode such as 'a' for append or 'w' for overwrite. This governs whether existing log content is preserved or truncated.

Why this answer

The 'mode' parameter controls the file opening mode (e.g., 'a' for append, 'w' for write).

40
Multi-Selectmedium

Which TWO of the following are required to successfully write a row to a CSV file?

Select 2 answers
A.A list of strings to write.
B.An instance of csv.writer.
C.A call to csv.close().
D.A predefined dialect.
E.A file object opened in write mode.
AnswersB, E

Writing rows requires a csv.writer instance, obtained by passing an open file object to csv.writer(). This object supplies the writerow() and writerows() methods that serialise Python sequences into delimited text, satisfying the stem's requirement for a mechanism that actually performs the CSV write operation.

Why this answer

To write a row to a CSV file with Python's csv module, you must first create an instance of csv.writer (option B), because csv.writer wraps a file-like object and provides the writerow()/writerows() methods that perform the CSV formatting and writing. You also need a file object opened in write mode (option E), such as one returned by open('file.csv', 'w', newline=''), since csv.writer writes to that underlying file object and cannot write to a path or a read-only handle. Option A is not required because the row data can be any iterable (e.g., tuple, generator), not strictly a list of strings, and the values need not all be strings since the writer converts them.

Option C is incorrect because there is no csv.close() function; you close the underlying file object (or use a with block), not the csv module. Option D is incorrect because a predefined dialect is optional — csv.writer defaults to the 'excel' dialect if none is supplied.

41
MCQhard

You are developing a Python script that needs to determine the absolute path of a file located in a directory relative to the script's location. You decide to use the os.path module. Which of the following functions should you use to obtain the absolute path without resolving symbolic links?

A.os.path.normpath()
B.os.path.realpath()
C.os.path.join()
D.os.path.abspath()
AnswerD

os.path.abspath() returns the absolute path of a given path, normalizing it by removing '..' and '.' components, but it does not resolve symbolic links. It simply prepends the current working directory if the path is relative. This is exactly what is needed when you want the absolute path without following symlinks. It is a straightforward and efficient way to get the absolute path.

Why this answer

os.path.abspath() computes an absolute path by combining the current working directory with the given path, normalizing it without resolving symbolic links. This matches the requirement. os.path.realpath() would resolve symlinks, os.path.normpath() only normalizes, and os.path.join() only concatenates components. Thus, abspath is the correct choice.

Exam trap

The trap here is confusing os.path.abspath() with os.path.realpath(), assuming both resolve symlinks, but only realpath does.

42
MCQhard

You are using configparser.ConfigParser to read a configuration file. You have a file where option names are case-sensitive. How do you ensure the parser respects this casing?

A.parser = ConfigParser(case_sensitive=True)
B.parser.set_case(True)
C.parser.optionxform = lambda x: x
D.parser.read(file, case='preserve')
AnswerC

Assigning an identity lambda to `optionxform` disables configparser's default lowercasing of option names, which is the mechanism that otherwise destroys case sensitivity. The stem's constraint — case-sensitive option names — is satisfied because keys are stored exactly as written in the file.

Why this answer

By default, ConfigParser converts keys to lowercase. You must override the optionxform method of the parser instance.

43
MCQhard

You are configuring logging using a dictConfig. You want to send logs to a RotatingFileHandler. Which key must you define in the 'handlers' section?

A.destination
B.type
C.handler_type
D.class
AnswerD

Specifying `class` tells dictConfig which handler type to instantiate, here `logging.handlers.RotatingFileHandler`, satisfying the requirement to route logs through a rotating file handler. Without it, dictConfig cannot resolve the handler factory, so the configuration fails. Other keys such as `filename` or `level` merely configure the instance after creation.

Why this answer

The 'class' key is required to specify the handler type, e.g., 'logging.handlers.RotatingFileHandler'.

44
MCQmedium

You need to configure the logging module to capture logs from multiple modules while ensuring that logs from third-party libraries (e.g., 'urllib3') are only captured at the WARNING level. How do you set this?

A.logging.getLogger('urllib3').setLevel(logging.WARNING)
B.logging.config.dictConfig({'urllib3': 'WARNING'})
C.logging.basicConfig(level=logging.WARNING)
D.logging.setLevel('urllib3', logging.WARNING)
AnswerA

Setting the level on the 'urllib3' logger object directly raises its effective threshold to WARNING, so DEBUG and INFO records from that library are discarded while your own modules keep their configured levels. This satisfies the constraint of suppressing third-party noise without altering root logger behaviour.

Why this answer

You can configure individual loggers using getLogger() and setting their specific level attribute.

45
MCQmedium

You are building a configuration manager that reads an INI file. A section contains the key-value pair `timeout = 30`. You need to retrieve the value as an integer, but if the key is missing, you want to get 60 without raising an exception. Which code snippet achieves this using the `configparser` module?

A.int(config.get('section', 'timeout', fallback=60))
B.config.getint('section', 'timeout', fallback=60)
C.config['section'].getint('timeout', 60)
D.config.getint('section', 'timeout', default=60)
AnswerB

The `getint` method of a `ConfigParser` instance converts the value to an integer and accepts a `fallback` keyword argument that is returned if the key is missing. This directly satisfies the requirement to get an integer or a default without raising an exception. The other options either do not convert to integer or do not handle missing keys gracefully.

Why this answer

The `getint` method of the `ConfigParser` class retrieves a value and converts it to an integer. It accepts a `fallback` argument that is returned if the key is not found, preventing a `NoOptionError`. This is the standard way to handle optional integer settings in INI files.

Exam trap

The trap here is confusing the `fallback` parameter of `configparser` methods with the `default` parameter used in other configuration libraries or the `default` argument of `dict.get`.

46
MCQmedium

You are processing a CSV file using csv.DictReader. If your input file lacks a header row, how do you provide the field names?

A.csv.DictReader(f, headers=['a', 'b'])
B.csv.DictReader(f).map(['a', 'b'])
C.csv.DictReader(f, fieldnames=['a', 'b'])
D.csv.DictReader(f, columns=['a', 'b'])
AnswerC

DictReader normally consumes the first row as field names. Passing fieldnames explicitly overrides that behaviour, so each subsequent row is mapped to the supplied keys in order, satisfying the constraint of a headerless file without manual index lookups.

Why this answer

You pass the 'fieldnames' argument to the constructor to define the headers explicitly.

47
MCQmedium

You are using sqlite3 and need to enforce foreign key constraints. How do you enable them?

A.It is enabled by default.
B.connection.execute('PRAGMA foreign_keys = ON')
C.connection.execute('SET FOREIGN_KEYS ON')
D.connection.enable_foreign_keys()
AnswerB

SQLite disables foreign key enforcement by default per connection, so the PRAGMA must be issued on the live connection object. Executing 'PRAGMA foreign_keys = ON' via connection.execute activates constraint checking for that session, satisfying the requirement to enforce referential integrity.

Why this answer

You must execute the command 'PRAGMA foreign_keys = ON;' on the connection.

48
Multi-Selecthard

Which TWO of the following are true about the sqlite3.Cursor object?

Select 2 answers
A.It can be used as an iterator to fetch rows.
B.It is used to execute SQL statements.
C.It automatically creates a transaction for every SELECT.
D.It is limited to one active query.
E.It keeps track of the connection state.
AnswersA, B

A Cursor implements the iterator protocol, so iterating it yields successive rows from the last executed SELECT without repeated fetchone calls. This is distinct from the Connection, which is not iterated for rows in this manner.

Why this answer

Option A is correct because a sqlite3.Cursor implements the iterator protocol, so you can loop over it directly (e.g., 'for row in cursor:') to fetch rows one at a time from the result set. Option B is correct because the Cursor object provides the execute(), executemany(), and executescript() methods that are used to run SQL statements against the database. Option C is incorrect because transaction handling is a property of the Connection object, not the Cursor; SELECT statements do not automatically open a transaction in the way described.

Option D is incorrect because a single Cursor can be reused for multiple sequential queries, and multiple cursors can exist on one connection. Option E is incorrect because connection state (such as open/closed status and transaction control) is tracked by the sqlite3.Connection object, not the Cursor.

Ready to test yourself?

Try a timed practice session using only Library Modules questions.