PCAP study materials
PCAP study resources

PCAP practice questions

One question at a time. Build your PCAP understanding.

First 50 of 200 questions. Each one lists the choices, the correct answer, and an explanation. The checker at the top of this page saves progress in this browser when it is available.

Continue in the practice tool above to load more questions, 50 at a time.

Question 1Modules and Packages

Which statement about a Python module is correct?

  1. A module can only be created from compiled C extensions.
  2. A module must contain a function named main to be importable.
  3. A module is a runtime object that exists only while a script executes.
  4. A module is a file containing Python definitions and statements whose name is the file name without the .py suffix. Correct answer.

Explanation

Any .py file is a module; its module name is the file name minus the .py extension. Importing executes the file's top-level code and binds the resulting module object. A main function is not required, and modules may be pure Python or extensions.

Question 2Modules and Packages

What does `import math` bind in the importing namespace?

  1. Each public function of math as a separate name.
  2. The name math referring to the math module object. Correct answer.
  3. The name math referring to the file path of the module.
  4. Nothing until a function from math is called.

Explanation

A plain `import math` binds only the module name in the current namespace. Individual attributes are accessed through that name, such as math.sqrt. Functions are not injected individually unless `from math import ...` is used.

Question 3Modules and Packages

Given a package directory `pkg` containing `__init__.py` and a submodule `tools.py`, which import statement makes `pkg.tools` accessible through the package attribute after execution?

  1. from pkg import
  2. import pkg.tools Correct answer.
  3. import tools
  4. from pkg.tools import

Explanation

`import pkg.tools` imports the submodule and binds the top-level name pkg, with tools available as an attribute of pkg. The other forms are syntactically incomplete or import the wrong name.

Question 4Modules and Packages

What is the purpose of the `__init__.py` file in a package?

  1. It stores the package version for the import system to read.
  2. It marks the directory as a package and runs when the package is imported. Correct answer.
  3. It is required only when the package contains C extensions.
  4. It lists every submodule that must be imported automatically.

Explanation

For regular packages, __init__.py marks the directory as a package and its code executes when the package is imported. It can be empty, and it does not automatically import submodules or store version metadata.

Question 5Modules and Packages

Which statement imports only the `sqrt` function from the `math` module?

  1. from math import sqrt Correct answer.
  2. from math import math.sqrt
  3. import math as sqrt
  4. import math.sqrt

Explanation

`from module import name` binds the named attribute directly in the current namespace. `import math.sqrt` is invalid syntax because the dotted name must resolve to a module, not a function, and aliasing with `as` binds the module.

Question 6Modules and Packages

What does `sys.path` contain?

  1. A set of already imported module names.
  2. A dictionary mapping module names to file paths.
  3. A tuple of built-in module names available in the interpreter.
  4. A list of strings that the import system searches for modules. Correct answer.

Explanation

sys.path is a list of directory and zip entries that the import system scans in order. Modifying it changes where imports can find modules. It is not a mapping, set, or tuple of names.

Question 7Modules and Packages

Which built-in variable holds the name of the current module, and equals `"__main__"` when the file is run as a script?

  1. __module__
  2. __package__
  3. __name__ Correct answer.
  4. __file__

Explanation

__name__ holds the module's name; when a file is executed directly as a script, the interpreter sets it to "__main__". This is the basis of the `if __name__ == "__main__":` guard.

Question 8Modules and Packages

A package `shop` contains `__init__.py` and `cart.py`. The file `shop/cart.py` contains `from . import models`. What does the leading dot signify?

  1. An import from the standard library.
  2. An import of a module named `models` in the current working directory.
  3. A relative import resolved against the current package. Correct answer.
  4. A deferred import executed only when models is first used.

Explanation

A leading dot in a from-import means a relative import, resolved relative to the package that contains the current module. Two dots would go up one level. It does not refer to the standard library or the working directory.

Question 9Modules and Packages

What does `importlib.reload(module)` do?

  1. It removes the module from sys.modules and imports a fresh copy.
  2. It restores the module to the version that was first imported.
  3. It reloads all modules that imported the given module.
  4. It re-executes the module's code in the existing module object's namespace. Correct answer.

Explanation

reload re-executes the module's top-level code using the existing module object's dictionary, so the object identity is preserved. It does not purge sys.modules or update dependent modules automatically.

Question 10Modules and Packages

A script does `import helpers` then `import helpers` again. How many times does the top-level code of helpers.py execute?

  1. Once per unique name bound in the importing namespace.
  2. Twice, because each import statement executes the file.
  3. Zero times, because only functions are imported.
  4. Once, because the module is cached in sys.modules. Correct answer.

Explanation

On the first import the module is executed and stored in sys.modules; later imports find the cached entry and skip re-execution. This makes imports cheap and gives modules singleton-like identity.

Question 11Modules and Packages

What does `from package import *` do when the package's `__init__.py` defines `__all__ = ["alpha", "beta"]`?

  1. It imports every name not starting with an underscore.
  2. It imports every submodule of the package.
  3. It imports only the names listed in __all__. Correct answer.
  4. It raises ImportError because packages cannot use star imports.

Explanation

When __all__ is defined, a star import binds exactly the names it lists. Without __all__, star imports bind public names (those not starting with an underscore). Star imports from packages are legal.

Question 12Modules and Packages

Which value of `__name__` is assigned to a module that is imported normally (not run as a script)?

  1. The module's import name, such as "pkg.tools". Correct answer.
  2. The name of the package that imported it.
  3. The string "__main__" regardless of how it is loaded.
  4. The absolute file path of the module.

Explanation

When a module is imported, __name__ is set to the name under which it was imported, including any package prefix. Only direct script execution sets it to "__main__".

Question 13Modules and Packages

A directory `plugins` contains `__init__.py` and `one.py`. After `import plugins.one`, what is bound in the local namespace?

  1. The name plugins, with one accessible as plugins.one. Correct answer.
  2. The name plugins.one as a single dotted identifier.
  3. The name one referring to the submodule.
  4. Both plugins and one as separate names.

Explanation

`import plugins.one` binds only the top-level package name plugins in the local namespace. The submodule is reached as an attribute, plugins.one. To bind one directly you would use `from plugins import one`.

Question 14Modules and Packages

What is the effect of a module-level `__all__` list on `from module import *`?

  1. It prevents the listed names from being accessed as attributes.
  2. It restricts the star import to the listed names. Correct answer.
  3. It forces every listed name to be imported eagerly at module load.
  4. It is documentation only and has no runtime effect.

Explanation

__all__ controls which names a star import exports. It does not change attribute access or force eager imports; it only affects the `import *` behavior.

Question 15Modules and Packages

Which statement about absolute and relative imports in Python 3 is correct?

  1. Relative imports search sys.path, while absolute imports resolve within the package.
  2. Absolute imports search sys.path, while relative imports resolve within the current package. Correct answer.
  3. Relative imports are only allowed in __init__.py files.
  4. Both absolute and relative imports always search the standard library first.

Explanation

In Python 3, absolute imports resolve against sys.path, while relative imports (leading dots) resolve relative to the current package. Relative imports are allowed in any module of a package, not only __init__.py.

Question 16Modules and Packages

What does the `__package__` attribute of a module indicate?

  1. The package the module belongs to, used to resolve relative imports. Correct answer.
  2. The directory on disk that contains the module file.
  3. The list of packages installed in the current environment.
  4. The module's parent class in its inheritance hierarchy.

Explanation

__package__ names the package context of a module and is used by the import system to resolve relative imports. For a top-level module it is typically empty or None; it is unrelated to installed packages or inheritance.

Question 17Modules and Packages

A directory named `data` with no `__init__.py` sits on sys.path. In Python 3.3+, what happens when code does `import data`?

  1. It raises ImportError because __init__.py is missing.
  2. It imports as a namespace package with no code executed. Correct answer.
  3. It is treated as a regular package and an empty __init__.py is generated.
  4. It imports every .py file in the directory as submodules.

Explanation

PEP 420 introduced namespace packages: a directory on sys.path without __init__.py can be imported as a package that has no __init__ code. No files are auto-imported and nothing is generated on disk.

Question 18Modules and Packages

Inside a module, code calls `importlib.import_module("a.b.c")`. Which name is bound in the caller's namespace?

  1. No name is bound, and the module object is discarded.
  2. The module object returned by the call, only if the caller assigns it. Correct answer.
  3. The name c, bound automatically.
  4. The top-level name a, bound automatically.

Explanation

import_module returns the module object but does not bind any name in the caller's namespace. To use it, the caller must assign the return value to a variable. Automatic binding happens only with the import statement.

Question 19Modules and Packages

A package's `__init__.py` contains `from .sub import helper`. What is a consequence of importing the package?

  1. The package import fails because __init__.py cannot import submodules.
  2. The name helper is bound only inside sub, not in the package namespace.
  3. The submodule sub is imported and helper becomes an attribute of the package. Correct answer.
  4. The submodule sub is imported only when helper is first called.

Explanation

Executing `from .sub import helper` in __init__.py imports the submodule and binds helper in the package's namespace, so pkg.helper works. This eager import runs at package import time.

Question 20Modules and Packages

Module `a` imports module `b`, and `b` imports `a` at top level. Under what condition does this circular import typically succeed?

  1. When sys.path lists the package directory twice.
  2. When the circular import is placed inside a function in both modules.
  3. When the names each module needs are defined before the other module is imported. Correct answer.
  4. When both modules use relative imports instead of absolute imports.

Explanation

Circular imports succeed if, by the time each module accesses the other, the needed names have already been bound. If access happens before definition, an AttributeError or ImportError results. Using relative imports or duplicating sys.path entries does not resolve ordering problems.

Question 21Modules and Packages

Which mechanism lets a package expose a submodule as if it were a top-level module without importing it eagerly?

  1. A module-level __getattr__ in __init__.py that imports on demand. Correct answer.
  2. A __path__ list that lists the submodule files.
  3. A sys.modules entry created at interpreter startup.
  4. A __all__ list that includes the submodule name.

Explanation

PEP 562 module-level __getattr__ is called when an attribute is not found, allowing lazy import of submodules. __all__ only affects star imports, __path__ controls package search paths, and sys.modules entries are created only after import.

Question 22Modules and Packages

What does `pkgutil.iter_modules()` yield when given a package's `__path__`?

  1. A list of file paths for every .pyc file in the path.
  2. ModuleInfo tuples describing importable modules found on that path. Correct answer.
  3. The names of packages that depend on the given package.
  4. The module objects already imported from the package.

Explanation

pkgutil.iter_modules scans the given path entries and yields ModuleInfo records (module finder, name, ispkg) for importable modules. It does not import them or return reverse dependencies.

Question 23Modules and Packages

A script run as `python app.py` contains `if __name__ == "__main__": main()`. What is the value of `__name__` inside app.py when it is instead imported by another module?

  1. "app" Correct answer.
  2. "__main__"
  3. "__init__"
  4. "main"

Explanation

When imported, __name__ is set to the module's import name, here "app", so the guard is false and main() is not called. Only direct execution sets __name__ to "__main__".

Question 24Modules and Packages

Which statement best describes how `sys.modules` differs from `sys.path`?

  1. Both are lists of search locations used during import.
  2. sys.modules maps names to already-imported modules, while sys.path lists search locations. Correct answer.
  3. Both are dictionaries keyed by module name.
  4. sys.modules lists search locations, while sys.path maps names to modules.

Explanation

sys.modules is a dictionary cache of imported modules keyed by name; sys.path is a list of locations searched when a name is not yet cached. They serve complementary roles in the import process.

Question 25Exceptions

Which base class must a user-defined exception inherit from so that it can be raised with the raise statement?

  1. SystemExit only
  2. The object class directly
  3. ExceptionGroup only
  4. BaseException or a subclass of it Correct answer.

Explanation

Any class derived from BaseException (directly or indirectly) can be raised. Exception is the conventional base for application errors, but BaseException is the root that makes raising legal.

Question 26Exceptions

What is the output of this code? try: x = 1 / 0 except ZeroDivisionError: print('A') finally: print('B')

  1. A then B Correct answer.
  2. B only
  3. A then an uncaught error
  4. A only

Explanation

The except block handles ZeroDivisionError and prints A; the finally block always runs afterwards, printing B. So both lines appear, in that order.

Question 27Exceptions

Which statement about the else clause of a try statement is correct?

  1. It runs only if an exception was caught
  2. It runs before the try block
  3. It replaces the finally block
  4. It runs only if the try block raised no exception Correct answer.

Explanation

The else suite executes when the try block completes without raising an exception. It runs after try and before finally.

Question 28Exceptions

What does the raise statement do when used with no arguments inside an except block?

  1. Raises a new generic Exception
  2. Re-raises the exception currently being handled Correct answer.
  3. Raises a RuntimeError
  4. Clears the active exception

Explanation

A bare raise inside an exception handler re-raises the exception that is currently being handled, preserving its traceback. It is only valid while an exception is active.

Question 29Exceptions

Which built-in exception is raised when you access a dictionary key that does not exist?

  1. IndexError
  2. AttributeError
  3. LookupError
  4. KeyError Correct answer.

Explanation

Missing dictionary keys raise KeyError. IndexError is for sequences, LookupError is a base class of KeyError, and AttributeError concerns missing attributes.

Question 30Exceptions

What happens when an exception is raised inside a finally block while another exception is already propagating?

  1. The program silently continues
  2. Both exceptions are raised together
  3. The original exception wins and the new one is ignored
  4. The new exception replaces the original one Correct answer.

Explanation

An exception raised in finally aborts the pending exception and propagates in its place, with the original attached as context. The original is effectively lost unless retrieved via __context__.

Question 31Exceptions

Given this code, what is printed? try: raise ValueError('v') except (TypeError, ValueError) as e: print(type(e).__name__)

  1. v
  2. ValueError Correct answer.
  3. Exception
  4. TypeError

Explanation

The except tuple matches ValueError, so the handler runs and prints the class name of the caught exception, which is ValueError.

Question 32Exceptions

What is the purpose of the as clause in an except statement?

  1. It aliases the exception class
  2. It binds the caught exception instance to a name Correct answer.
  3. It selects which exception to ignore
  4. It renames the traceback

Explanation

The as clause binds the exception instance to a local name inside the handler. That name is deleted automatically at the end of the except block.

Question 33Exceptions

What is the value of e.__cause__ when an exception is raised with 'raise NewError from orig'?

  1. The NewError instance itself
  2. None
  3. The orig exception object Correct answer.
  4. A string with orig's message

Explanation

The 'raise ... from orig' form sets __cause__ to orig and also sets __suppress_context__ to True. This explicitly chains the new exception to the original.

Question 34Exceptions

How does implicit exception chaining differ from explicit chaining?

  1. Implicit chaining disables chaining entirely
  2. Both set only __traceback__
  3. Implicit chaining sets __cause__; explicit chaining sets __context__
  4. Implicit chaining sets __context__; explicit chaining sets __cause__ Correct answer.

Explanation

When an exception is raised while another is being handled, Python sets __context__ automatically (implicit chaining). Using 'raise ... from ...' sets __cause__ (explicit chaining).

Question 35Exceptions

What does 'raise SomeError from None' accomplish?

  1. It disables all tracebacks
  2. It makes the error non-catchable
  3. It converts the error to a warning
  4. It suppresses display of the implicit context Correct answer.

Explanation

Passing None as the cause sets __suppress_context__ to True, so the implicit context is not shown in the traceback. The exception is still fully catchable.

Question 36Exceptions

Which exception class is the recommended base for user-defined exceptions that represent application errors?

  1. Exception Correct answer.
  2. BaseException
  3. GeneratorExit
  4. KeyboardInterrupt

Explanation

User exceptions should normally subclass Exception so they are handled by typical 'except Exception' handlers and do not collide with system-exit signals.

Question 37Exceptions

What is printed? try: try: raise KeyError('k') finally: print('inner') except KeyError: print('outer')

  1. inner then outer Correct answer.
  2. inner only
  3. outer only
  4. outer then inner

Explanation

The inner finally runs as the KeyError propagates out of the inner try, printing 'inner'. The outer except then catches it and prints 'outer'.

Question 38Exceptions

When an exception is not handled anywhere in the call stack, what does Python do?

  1. It silently ignores the exception
  2. It prints a traceback and terminates the program Correct answer.
  3. It converts the exception to a warning
  4. It retries the failing statement

Explanation

An unhandled exception propagates to the top level, where the interpreter prints the traceback to stderr and exits with a non-zero status.

Question 39Exceptions

What happens to the name bound by 'except E as e' after the except block finishes?

  1. e keeps referencing the exception
  2. e is rebound to the exception class
  3. The name e is deleted Correct answer.
  4. e becomes None

Explanation

Python deletes the target name at the end of the except block to break reference cycles with the traceback. Referencing it afterwards raises NameError.

Question 40Exceptions

Which exception is raised by the assert statement when its condition is false?

  1. AssertionError Correct answer.
  2. SyntaxError
  3. ValueError
  4. RuntimeError

Explanation

A failing assert raises AssertionError with an optional message. Asserts can be stripped when Python runs with optimization (-O).

Question 41Exceptions

What is the effect of running Python with the -O flag on assert statements?

  1. Asserts raise AssertionError more eagerly
  2. Asserts print a warning instead
  3. Asserts become try/except blocks
  4. Assert statements are removed from the bytecode Correct answer.

Explanation

Optimization mode compiles out assert statements, so they do not execute. Code must not rely on asserts for essential validation.

Question 42Exceptions

Which built-in exception is the base class of both KeyError and IndexError?

  1. ValueError
  2. TypeError
  3. RuntimeError
  4. LookupError Correct answer.

Explanation

LookupError is the common ancestor of exceptions raised for failed lookups, including KeyError and IndexError. Catching LookupError catches both.

Question 43Exceptions

What is printed? def f(): return 1 try: f() except Exception: print('caught') else: print('ok') finally: print('done')

  1. done only
  2. ok then done Correct answer.
  3. caught then done
  4. ok only

Explanation

No exception occurs, so the else clause runs and prints 'ok'. The finally clause always runs and prints 'done' afterwards.

Question 44Exceptions

Which exception type is raised when an operation uses an object of an inappropriate type, such as adding an int to a string?

  1. ValueError
  2. TypeError Correct answer.
  3. AttributeError
  4. NameError

Explanation

TypeError signals that an operation received an object of an unsupported type. ValueError would indicate a correct type with an invalid value.

Question 45Exceptions

How can a single except clause handle several distinct exception types?

  1. Chain them with the or keyword
  2. Separate them with commas without parentheses
  3. List them in a tuple after except Correct answer.
  4. Use one except clause per type only

Explanation

An except clause accepts a tuple of exception classes and matches if the raised exception is an instance of any of them.

Question 46Exceptions

What does the __context__ attribute of an exception hold when implicit chaining occurs?

  1. The message of the current exception
  2. The name of the function that raised it
  3. The traceback object
  4. The previously active exception being handled Correct answer.

Explanation

__context__ references the exception that was active when the new one was raised, enabling implicit chaining. __cause__ is reserved for explicit 'from' chaining.

Question 47Exceptions

What is the result of the following code? try: raise ValueError('x') except Exception as e: pass print(e)

  1. It prints ValueError
  2. It prints x
  3. It prints None
  4. It raises NameError Correct answer.

Explanation

The name bound by 'as e' is deleted when the except block ends, so referencing e afterwards raises NameError.

Question 48Exceptions

Which statement about BaseException subclasses such as KeyboardInterrupt and SystemExit is correct?

  1. They cannot be raised by user code
  2. They are not caught by 'except Exception' Correct answer.
  3. They are subclasses of Exception
  4. They are always silently ignored

Explanation

KeyboardInterrupt and SystemExit inherit from BaseException but not from Exception, so a handler for Exception does not catch them. This lets shutdown signals bypass ordinary error handling.

Question 49Exceptions

What is printed? def g(): try: return 'try' finally: return 'finally' print(g())

  1. finally Correct answer.
  2. A RuntimeError is raised
  3. try
  4. try then finally

Explanation

A return inside finally overrides any pending return from the try block, so the function returns 'finally'. This is a common source of subtle bugs.

Question 50Exceptions

Which built-in exception is raised when a function receives an argument whose value is of the correct type but is outside the acceptable range?

  1. RangeError
  2. ValueError Correct answer.
  3. IndexError
  4. TypeError

Explanation

ValueError signals that an argument has the right type but an unsuitable value, such as a negative number passed where a positive one is required. TypeError is reserved for wrong types, and IndexError applies to sequence indexing, not general argument validation.