Courseiva
Knowledge + Practice
CertificationsVendorsCareer RoadmapsLabs & ToolsStudy GuidesGlossaryPractice Questions
C
Courseiva

Free IT certification practice questions with explained answers for CCNA, CompTIA, AWS, Azure, Google Cloud, and more.

Certification Practice Questions

CCNA practice questionsSecurity+ SY0-701 practice questionsAWS SAA-C03 practice questionsAZ-104 practice questionsAZ-900 practice questionsCLF-C02 practice questionsA+ Core 1 practice questionsGoogle Cloud ACE practice questionsCySA+ CS0-003 practice questionsNetwork+ N10-009 practice questions
View all certifications →

Product

CertificationsCertification PathsExam TopicsPractice TestsExam Dumps vs Practice TestsStudy HubComparisons

Company

AboutContactEditorial PolicyQuestion Writing PolicyTrust Center

Legal

Privacy PolicyTerms of Service

Courseiva is a free IT certification practice platform offering original exam-style practice questions, detailed explanations, topic-based practice, mock exams, readiness tracking, and study analytics for Cisco, CompTIA, Microsoft, AWS, and other technology certifications.

© 2026 Courseiva. Courseiva is operated by JTNetSolutions Ltd. All rights reserved.

Courseiva is an independent certification practice platform and is not affiliated with, endorsed by, or sponsored by Cisco, Microsoft, AWS, CompTIA, Google, ISC2, ISACA, or any other certification vendor. Vendor names and certification marks are used only to identify the exams learners are preparing for.

HomeCertificationsPCAPExam Questions

Python Institute · Free Practice Questions · Last reviewed May 2026

PCAP Exam Questions and Answers

24real exam-style questions organised by domain, each with the correct answer highlighted and a plain-English explanation of why it's right — and why the others are wrong.

40 exam questions
65 min time limit
Pass: 700/1000 / 1000
4 exam domains
OverviewDomain BlueprintStudy GuideAll QuestionsSample by Domain
1. Modules and Packages2. Strings3. Object-Oriented Programming4. Exceptions and File I/O
1

Domain 1: Modules and Packages

All Modules and Packages questions
Q1
mediumFull explanation →

A developer is working on a project that requires the use of a third-party package hosted on a private repository. The developer wants to ensure that the package can be imported without specifying the full repository URL each time. Which approach should be taken?

A

Append the repository path to sys.path in the script.

B

Place the package files in the site-packages directory manually.

C

Configure the repository URL in pip's configuration file or in requirements.txt.

pip configuration allows specifying extra index URLs for package resolution.

D

Use os.system to run a pip install command from within the script.

Why: Option C is correct because configuring the repository URL in pip's configuration file (e.g., `pip.conf`, `pip.ini`, or `~/.config/pip/pip.conf`) or in `requirements.txt` using the `--index-url` or `--extra-index-url` option allows pip to resolve the package from the private repository automatically. This approach ensures that the package can be installed and imported without manually specifying the full URL each time, as pip will use the configured index to locate and download the package.
Q2
easyFull explanation →

A Python script imports the module 'my_module'. The developer wants to ensure that when the script is run directly, it executes a specific function, but when imported as a module, that function is not executed. Which code snippet achieves this?

A

if __name__ == '__main__': run()

B

if __name__ == '__main__': run()

This is the standard Python idiom for executable scripts.

C

if os.environ.get('RUN_MAIN'): run()

D

if sys.argv[0] == 'my_module': run()

Why: Option B is correct because the `if __name__ == '__main__':` guard is the standard Python idiom to check whether a script is being run directly (as the main program) or being imported as a module. When the script is executed directly, Python sets the special variable `__name__` to the string `'__main__'`, so the function `run()` is called. When the script is imported, `__name__` is set to the module's name (e.g., `'my_module'`), so the condition fails and `run()` is not executed.
Q3
hardFull explanation →

A developer creates a package named 'analytics' with the following structure:

analytics/ __init__.py stats.py models/ __init__.py regression.py

The developer wants the statement 'from analytics import *' to import only the functions 'mean' and 'std' from stats.py. What should be added to analytics/__init__.py?

A

Nothing; by default, all names are exported.

B

from analytics.stats import *

C

__all__ = ['stats.mean', 'stats.std']

D

__all__ = ['mean', 'std']

This defines the public API of the package.

Why: Option D is correct because in Python, the `__all__` variable in a package's `__init__.py` explicitly controls which names are exported when `from package import *` is used. By setting `__all__ = ['mean', 'std']`, the developer ensures that only the functions `mean` and `std` from `stats.py` are imported into the namespace, as Python will look up these names in the package's scope after executing the `__init__.py` file. This overrides the default behavior where all public names (those not starting with an underscore) would be exported.
Q4
mediumFull explanation →

A developer is troubleshooting an ImportError: 'No module named 'config''. The config module is located in a subdirectory 'utils' relative to the script. The script's current working directory is the parent of 'utils'. Which of the following lines, added to the script, will resolve the issue?

A

sys.path.append('utils/config.py')

B

sys.path.append('utils')

This adds the utils directory to the module search path.

C

sys.path = os.path.join(sys.path, 'utils')

D

os.chdir('utils')

Why: The ImportError occurs because Python's module search path (sys.path) does not include the 'utils' subdirectory. Adding 'utils' to sys.path via sys.path.append('utils') tells Python to look inside that directory for modules, resolving the import. Option B is correct because it extends the search path to include the directory containing the config module, without altering the script's working directory or incorrectly appending a file path.
Q5
easyFull explanation →

A developer wants to import a specific function 'calculate' from a module named 'formulas' without importing the entire module. Which import statement should be used?

A

import formulas

B

import calculate from formulas

C

from formulas import calculate

This imports only the specified function.

D

import formulas as f

Why: Option C is correct because the `from module import name` syntax in Python allows you to import a specific function (or other attribute) from a module directly into the current namespace, without importing the entire module. This avoids unnecessary memory usage and keeps the namespace clean by only bringing in the needed `calculate` function.
Q6
hardFull explanation →

A developer notices that a custom package 'mypackage' is not being found when importing, even though it is installed in the site-packages directory. The developer suspects a conflict with another package of the same name. Which command should the developer run to diagnose the location from which Python is importing the package?

A

print(mypackage)

B

print(__file__)

C

print(mypackage.__file__)

This attribute contains the path to the module's file.

D

import os; print(os.getcwd())

Why: Option C is correct because `mypackage.__file__` returns the filesystem path from which the module was loaded, allowing the developer to see exactly which `mypackage` Python is using. This directly reveals if the wrong package (e.g., from a different location or a conflicting installation) is being imported instead of the intended one.

Want more Modules and Packages practice?

Practice this domain
2

Domain 2: Strings

All Strings questions
Q1
mediumFull explanation →

A developer needs to count the number of occurrences of the substring 'is' in the string 'This is a test. Is this a test?'. Which code correctly performs the count?

A

'This is a test. Is this a test?'.split().count('is')

B

'This is a test. Is this a test?'.count('is')

Correctly counts overlapping? No, count does not count overlapping, but 'is' appears at positions 5 and 17, not overlapping, so returns 2.

C

'This is a test. Is this a test?'.index('is')

D

'This is a test. Is this a test?'.find('is')

Why: Option B is correct because Python's string method `count(substring)` returns the number of non-overlapping occurrences of the substring in the string. In 'This is a test. Is this a test?', 'is' appears twice (in 'This' and 'is'), and the method counts them correctly, ignoring case sensitivity (the capitalized 'Is' is not counted).
Q2
mediumFull explanation →

A programmer writes a function to check if a string is a palindrome (ignoring case and non-alphanumeric characters). Which implementation correctly achieves this?

A

def is_pal(s): s = s.lower(); return s == ''.join(reversed(s))

B

def is_pal(s): s = ''.join(c for c in s if c.isalnum()).lower(); return s == s[::-1]

Correctly filters alphanumeric, lowercases, and compares reverse.

C

def is_pal(s): return s == s[::-1]

D

def is_pal(s): s = s.lower(); return s == s[::-1]

Why: Option B is correct because it first filters the string to keep only alphanumeric characters using `c.isalnum()`, converts the result to lowercase with `.lower()`, and then compares the string to its reverse using slicing `s[::-1]`. This correctly handles case insensitivity and ignores non-alphanumeric characters, which is the standard approach for palindrome checking in Python.
Q3
hardFull explanation →

A log analysis script needs to extract all IP addresses from a string. The IPs are in dotted-decimal format. Which regex pattern will correctly extract them?

A

r'[0-9]+\. [0-9]+\.[0-9]+\.[0-9]+'

B

r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'

C

r'(?:[0-9]{1,3}\.){3}[0-9]{1,3}'

Matches three groups of 1-3 digits followed by dot, then one more group. Does not validate range beyond 999, but typical for IP extraction.

D

r'\d+\.\d+\.\d+\.\d+'

Why: Option C is correct because it uses a non-capturing group `(?:...)` to repeat the pattern `[0-9]{1,3}\.` exactly three times, followed by a final octet `[0-9]{1,3}`. This matches the dotted-decimal structure of an IPv4 address (four octets, each 1–3 digits, separated by dots) without introducing extra spaces or overly permissive digit counts, and it avoids capturing unnecessary groups.
Q4
easyFull explanation →

Which string method can be used to check if a string contains only digits?

A

str.isdigit()

Returns True if all characters are digits (0-9).

B

str.isalnum()

C

str.isdecimal()

D

str.isnumeric()

Why: The `str.isdigit()` method returns `True` if all characters in the string are digits (0-9) and the string is non-empty. This is the most direct and commonly used method for checking numeric-only strings in Python, as it specifically tests for digit characters without including other numeric forms like fractions or Roman numerals.
Q5
mediumFull explanation →

A developer needs to replace all occurrences of 'cat' with 'dog' in a string, but only if 'cat' is a whole word (not part of 'category'). Which code achieves this?

A

re.sub(r'\bcat\b', 'dog', s)

Word boundaries ensure whole word match.

B

s.replace('cat', 'dog')

C

re.sub('cat', 'dog', s)

D

s.replace('cat', 'dog', 1)

Why: Option A uses the `re.sub()` function with the regex pattern `r'\bcat\b'`, where `\b` denotes a word boundary. This ensures that only the whole word 'cat' is matched and replaced with 'dog', ignoring cases where 'cat' appears as part of a larger word like 'category'. The `r` prefix makes it a raw string, preventing escape sequence issues.
Q6
hardFull explanation →

Given the string s = 'Hello World!', which expression returns a list of characters?

A

s.split('')

B

list(s)

Converts string to list of characters.

C

s.split()

D

s.split(' ')

Why: Option B is correct because the `list()` constructor, when passed a string, iterates over each character in the string and returns a list where each element is a single character. For `s = 'Hello World!'`, `list(s)` produces `['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!']`, which is exactly a list of characters.

Want more Strings practice?

Practice this domain
3

Domain 3: Object-Oriented Programming

All Object-Oriented Programming questions
Q1
easyFull explanation →

A developer creates a Python class with a method that is intended to be overridden in subclasses. Which approach best ensures that the method is not accidentally called on the base class?

A

Use 'pass' as the method body

B

Delete the method from the base class using 'del'

C

Add a comment '# override in subclass' inside the method body

D

Raise NotImplementedError inside the method body

Raising NotImplementedError clearly signals the method must be overridden.

Why: Raising NotImplementedError inside the base class method is the standard Python idiom for defining an abstract-like method that must be overridden in subclasses. If a subclass fails to override the method and it is called, Python will raise an explicit error at runtime, preventing accidental use of the base implementation. This approach enforces the contract that the method is intended only for subclasses, without requiring the `abc` module.
Q2
easyFull explanation →

A developer wants to ensure that a class attribute is shared among all instances but cannot be modified from outside the class. Which approach is most appropriate?

A

Use a property decorator on a class method

B

Define a public class attribute and document it as read-only

C

Define an instance attribute inside __init__

D

Define a private class attribute (e.g., __shared) and provide a class method to access it

Name mangling discourages direct access; getter method controls read-only access.

Why: Option D is correct because defining a private class attribute with name mangling (e.g., `__shared`) prevents direct external modification, and providing a class method (using `@classmethod`) allows read-only access to the attribute. This ensures the attribute is shared among all instances (since it belongs to the class, not instances) while enforcing encapsulation.
Q3
mediumFull explanation →

A Python class 'BankAccount' has a method 'withdraw(amount)' that deducts 'amount' from 'self.balance'. A developer writes a subclass 'SavingsAccount' that overrides 'withdraw' to add a penalty if balance drops below minimum. Which design pattern is being used?

A

Composition

B

Aggregation

C

Method overriding

The subclass provides a specific implementation of the inherited method.

D

Inheritance

Why: Option C is correct because method overriding is the mechanism where a subclass provides a specific implementation of a method that is already defined in its superclass. In this scenario, SavingsAccount overrides the withdraw method from BankAccount to add penalty logic, which is the defining characteristic of method overriding in Python.
Q4
mediumFull explanation →

A team is developing a system that must handle different types of documents (PDF, Word, etc.). Each document type has a unique parsing method. To avoid massive conditional logic, which OOP concept should be applied?

A

Polymorphism

Polymorphism enables each subclass to provide its own implementation of a common interface.

B

Encapsulation

C

Inheritance

D

Abstraction

Why: Polymorphism allows different document types (PDF, Word, etc.) to be treated uniformly through a common interface (e.g., a `parse()` method) while each class implements its own parsing logic. This eliminates the need for conditional statements (like `if type == 'PDF'`) because the correct method is resolved at runtime via dynamic dispatch, which is exactly what the team needs to avoid massive conditional logic.
Q5
hardFull explanation →

A developer writes a class 'Logger' with a class method 'log(msg)' that writes to a file. Another class 'AppLogger' inherits from 'Logger'. The developer expects both classes to share the same file handle. However, after creating an instance of 'AppLogger', the file handle is different. What is the most likely cause?

A

The 'log' method is defined as a class method using @classmethod

B

The file handle is opened in the __init__ method of the base class

Opening in __init__ creates a new handle per instance, not shared.

C

The file handle is stored as a private attribute __file

D

The subclass overrides the 'log' method

Why: Option B is correct because if the file handle is opened in the `__init__` method of the base class, each time a new instance is created (including when an `AppLogger` instance is created), a new file handle is opened. This means the `Logger` class and the `AppLogger` class do not share the same file handle; instead, each instance gets its own handle. To share a single file handle across all instances, the file handle should be opened as a class attribute or in a class method, not in `__init__`.
Q6
hardFull explanation →

A class 'MyClass' has a method 'do_something' that uses 'self.__private'. A subclass 'MySubClass' tries to access 'self.__private' and gets an AttributeError. Why?

A

Because the attribute is defined as a class attribute, not instance attribute

B

Because the subclass overrides the method that uses the attribute

C

Because name mangling renames the attribute to _MyClass__private, and the subclass implicitly accesses _MySubClass__private

Each class gets its own name-mangled version.

D

Because the attribute is private and not inherited

Why: Option C is correct because Python's name mangling mechanism renames any attribute prefixed with double underscores (like `__private`) in a class definition to `_ClassName__private`. When `MySubClass` tries to access `self.__private`, Python looks for `_MySubClass__private`, which does not exist, causing an AttributeError. The attribute `_MyClass__private` is still accessible from the subclass, but only via its mangled name.

Want more Object-Oriented Programming practice?

Practice this domain
4

Domain 4: Exceptions and File I/O

All Exceptions and File I/O questions
Q1
easyFull explanation →

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

FileNotFoundError is specifically for missing files.

B

PermissionError

C

IOError

D

OSError

Why: Option A is correct because `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.
Q2
mediumFull explanation →

A Python script processes a log file line by line. If a line cannot be decoded due to an encoding error, the script should skip the line and continue. Which exception handling approach is best?

A

Wrap the entire file reading in a try-except block without specifying exception type.

B

Use a try-except-else block to handle success and failure separately, exiting on failure.

C

Inside the loop, wrap the line decoding in a try-except UnicodeDecodeError block and continue.

This isolates decoding issues and continues processing.

D

Catch Exception in the outer loop and break on error.

Why: Option C is correct because it places the try-except block inside the loop, specifically catching `UnicodeDecodeError` for each line. This allows the script to skip only the problematic line and continue processing subsequent lines, which matches the requirement exactly.
Q3
hardFull explanation →

A developer implements a custom exception class `DataError` that inherits from `Exception`. Which method override is essential to ensure the exception message is properly displayed when caught?

A

Override __init__ to accept a message and call super().__init__(message).

This ensures the message is stored and displayed.

B

Set the __cause__ attribute in __init__.

C

Override __str__ to return a formatted string.

D

Override __repr__ to return a detailed representation.

Why: Option A is correct because the `Exception` class's `__init__` method stores the message argument in the `args` attribute, which is used by the default `__str__` method to display the message. By overriding `__init__` to accept a message and call `super().__init__(message)`, the custom exception properly passes the message to the base class, ensuring it is displayed when caught and printed.
Q4
easyFull explanation →

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

'w' mode overwrites existing content.

C

open('file.txt', 'r+')

D

open('file.txt', 'a')

Why: Option B is correct because 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.
Q5
mediumFull explanation →

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)

Reads up to 4 bytes.

B

f.seek(4)

C

f.readline()

D

f.read()

Why: 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.
Q6
hardFull explanation →

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

ZeroDivisionError is raised and caught.

D

Invalid integer

Why: 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.

Want more Exceptions and File I/O practice?

Practice this domain

Frequently asked questions

How many questions are on the PCAP exam?

The PCAP exam has 40 questions and must be completed in 65 minutes. The passing score is 700/1000.

What types of questions appear on the PCAP exam?

Scenario-based questions covering exam objectives with detailed answer explanations.

How are PCAP questions organised by domain?

The exam covers 4 domains: Modules and Packages, Strings, Object-Oriented Programming, Exceptions and File I/O. Questions are weighted by domain — higher-weight domains appear more on your actual exam.

Are these the actual PCAP exam questions?

No. These are original exam-style practice questions written against the official Python Institute PCAP exam objectives. They are not copied from the real exam. Courseiva focuses on genuine understanding, not memorisation of braindumps.

Ready to practice all 40 PCAP questions?

Courseiva tracks your accuracy per domain and routes you toward weak areas automatically. Free, no account required.

Browse all PCAP questionsTake a timed practice test