Practice Questions — Modules and Packages in Python
← Back to NotesTopic-Specific Questions
Question 1
Easy
What is the output of the following code?
import math
print(math.sqrt(64))math.sqrt() returns the square root as a float.
8.0Question 2
Easy
What is the output?
from math import pi
print(round(pi, 2))pi is approximately 3.14159. round() rounds to the given decimal places.
3.14Question 3
Easy
What is the output?
import math
print(math.ceil(4.1))
print(math.floor(4.9))ceil rounds up, floor rounds down.
54Question 4
Easy
What is the output?
from math import factorial
print(factorial(5))5! = 5 * 4 * 3 * 2 * 1
120Question 5
Easy
What is the output?
import math as m
print(m.gcd(12, 18))gcd returns the greatest common divisor. math is aliased as m.
6Question 6
Medium
What is the output?
import random
random.seed(0)
print(random.randint(1, 10))
print(random.randint(1, 10))
random.seed(0)
print(random.randint(1, 10))Setting the same seed produces the same sequence of random numbers.
717Question 7
Medium
What is the output?
from datetime import date
d1 = date(2026, 1, 1)
d2 = date(2026, 4, 6)
diff = d2 - d1
print(diff.days)
print(type(diff).__name__)Subtracting two date objects gives a timedelta.
95timedeltaQuestion 8
Medium
What is the output?
import json
data = {"name": "Aarav", "scores": [85, 92]}
json_str = json.dumps(data)
print(type(json_str).__name__)
print(json_str)
parsed = json.loads(json_str)
print(type(parsed).__name__)
print(parsed["name"])dumps converts to string, loads converts back to dict.
str{"name": "Aarav", "scores": [85, 92]}dictAaravQuestion 9
Medium
What is the output?
import os.path
print(os.path.join("folder", "subfolder", "file.txt"))
print(os.path.splitext("report.pdf"))
print(os.path.basename("/home/user/data.csv"))os.path functions handle file paths in a cross-platform way.
folder/subfolder/file.txt('report', '.pdf')data.csvQuestion 10
Medium
What is the output?
import math
print(math.pow(2, 10))
print(2 ** 10)
print(type(math.pow(2, 10)).__name__)
print(type(2 ** 10).__name__)math.pow always returns a float. The ** operator preserves the integer type.
1024.01024floatintQuestion 11
Medium
What is the output?
import json
python_data = {"active": True, "count": None, "items": ()}
json_str = json.dumps(python_data)
print(json_str)JSON has different representations for True, None, and tuples.
{"active": true, "count": null, "items": []}Question 12
Hard
What is the output?
import sys
a = []
b = [1, 2, 3]
c = "hello"
print(sys.getsizeof(a) < sys.getsizeof(b))
print(sys.getsizeof("") < sys.getsizeof(c))
print(sys.getsizeof(0) == sys.getsizeof(1000))Lists with more elements use more memory. Longer strings use more memory. Small ints have the same base size.
TrueTrueTrueQuestion 13
Hard
What is the output?
import math
values = [0.1, 0.2, 0.3, 0.4]
print(sum(values))
print(math.fsum(values))
print(sum(values) == 1.0)
print(math.fsum(values) == 1.0)Floating-point arithmetic has precision issues. math.fsum reduces these errors.
0.99999999999999991.0FalseTrueQuestion 14
Hard
What is the output?
import json
data = {"b": 2, "a": 1, "c": 3}
print(json.dumps(data))
print(json.dumps(data, sort_keys=True))
print(json.dumps(data, indent=2, sort_keys=True)[:20])sort_keys orders dictionary keys alphabetically. indent adds pretty formatting.
{"b": 2, "a": 1, "c": 3}{"a": 1, "b": 2, "c": 3}{
"a": 1,
"b":Question 15
Hard
What is the output?
from math import sqrt, pow, pi
import math
print(sqrt(16)) # from...import
print(math.sqrt(16)) # import
print(sqrt is math.sqrt)Both import styles access the same underlying function object.
4.04.0TrueQuestion 16
Medium
What is the difference between
json.dump() and json.dumps()?The 's' in dumps stands for 'string'.
json.dump(data, file) writes JSON directly to a file object. json.dumps(data) returns a JSON-formatted string. Similarly, json.load(file) reads from a file, while json.loads(string) parses a string. The 's' stands for 'string'.Question 17
Hard
Why should you never name your Python file
random.py or math.py?Think about the module search order. Where does Python look first?
Python searches for modules starting with the current directory. If you create a file called
random.py, Python imports YOUR file instead of the standard library random module. This shadows the standard library module, causing AttributeError when you try to use functions like random.randint().Mixed & Application Questions
Question 1
Easy
What is the output?
import math
print(math.ceil(-3.2))
print(math.floor(-3.2))ceil goes toward positive infinity, floor goes toward negative infinity.
-3-4Question 2
Easy
What is the output?
import random
random.seed(42)
colors = ["red", "green", "blue"]
print(random.choice(colors))
print(random.choice(colors))With a fixed seed, the sequence is deterministic.
greengreenQuestion 3
Medium
What is the output?
import json
original = {"x": (1, 2, 3)}
json_str = json.dumps(original)
restored = json.loads(json_str)
print(type(original["x"]).__name__)
print(type(restored["x"]).__name__)
print(original == restored)JSON has no tuple type. What does a tuple become after JSON round-trip?
tuplelistFalseQuestion 4
Medium
What is the output?
from math import sqrt
def distance(x1, y1, x2, y2):
return sqrt((x2-x1)**2 + (y2-y1)**2)
print(distance(0, 0, 3, 4))
print(distance(1, 1, 4, 5))This is the Euclidean distance formula. sqrt(9+16) = sqrt(25) = 5.
5.05.0Question 5
Medium
What is the output?
from datetime import timedelta
one_week = timedelta(weeks=1)
two_days = timedelta(days=2)
total = one_week + two_days
print(total.days)
print(total > one_week)timedelta objects can be added and compared.
9TrueQuestion 6
Medium
What is the output?
import math
numbers = [4, 9, 16, 25, 36]
roots = [math.sqrt(n) for n in numbers]
print(roots)
print([int(r) for r in roots])math.sqrt returns floats. int() truncates the decimal.
[2.0, 3.0, 4.0, 5.0, 6.0][2, 3, 4, 5, 6]Question 7
Hard
What is the output?
import json
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
s = Student("Priya", 15)
try:
print(json.dumps(s))
except TypeError as e:
print(f"Error: {type(e).__name__}")
print(json.dumps(s.__dict__))json.dumps cannot serialize custom objects directly. __dict__ gives the object's attributes as a dict.
Error: TypeError{"name": "Priya", "age": 15}Question 8
Hard
What is the output?
import math
def classify_number(n):
if math.isinf(n):
return "infinite"
if math.isnan(n):
return "not a number"
if n == int(n):
return "whole"
return "decimal"
print(classify_number(5.0))
print(classify_number(3.14))
print(classify_number(float('inf')))
print(classify_number(float('nan')))math.isinf and math.isnan check for special float values.
wholedecimalinfinitenot a numberQuestion 9
Hard
What is the output?
import random
random.seed(10)
nums = list(range(1, 6)) # [1, 2, 3, 4, 5]
sampled = random.sample(nums, 3)
print(f"sample: {sampled}")
print(f"original: {nums}")
random.shuffle(nums)
print(f"shuffled: {nums}")sample returns a new list (original unchanged). shuffle modifies the list in place.
sample: [2, 1, 5]original: [1, 2, 3, 4, 5]shuffled: [5, 3, 4, 1, 2]Question 10
Hard
What is the output?
import math
print(math.log(1)) # Natural log of 1
print(math.log(math.e)) # Natural log of e
print(math.log(100, 10)) # Log base 10 of 100
print(math.log2(8)) # Log base 2 of 8ln(1) = 0, ln(e) = 1, log10(100) = 2, log2(8) = 3.
0.01.02.03.0Question 11
Medium
What happens when Python executes
import mymodule for the first time?Think about module search, execution, and caching.
Python (1) searches for
mymodule.py in the module search path (sys.path), (2) creates a new module object, (3) executes all the code in the file from top to bottom, (4) binds the module object to the name mymodule in the current namespace, and (5) caches the module in sys.modules so subsequent imports use the cached version without re-executing the code.Multiple Choice Questions
MCQ 1
What is a module in Python?
Answer: B
B is correct. A module is simply a
B is correct. A module is simply a
.py file containing Python code (functions, classes, variables). Any Python file can be imported as a module.MCQ 2
Which statement imports only the sqrt function from the math module?
Answer: B
B is correct.
B is correct.
from math import sqrt imports only sqrt into your namespace. Option A tries to import a sub-module (not valid for functions). Options C and D are not valid Python syntax.MCQ 3
What does import random as rnd do?
Answer: B
B is correct. The
B is correct. The
as keyword creates an alias. rnd is just another name for the same module object. The module is not copied or renamed -- you simply refer to it using a shorter name.MCQ 4
What does math.ceil(3.1) return?
Answer: B
B is correct.
B is correct.
math.ceil() returns the smallest integer greater than or equal to the argument. Since 3.1 is between 3 and 4, ceil returns 4.MCQ 5
Which function from the random module picks a random element from a list?
Answer: C
C is correct.
C is correct.
random.choice(sequence) returns a randomly selected element from a non-empty sequence. The other function names do not exist in the random module.MCQ 6
What does the __name__ variable equal when a Python file is run directly?
Answer: B
B is correct. When a Python file is executed directly (not imported),
B is correct. When a Python file is executed directly (not imported),
__name__ is set to "__main__". When the file is imported as a module, __name__ is set to the module name.MCQ 7
What is the purpose of __init__.py in a directory?
Answer: B
B is correct. The
B is correct. The
__init__.py file tells Python that the directory should be treated as a package (a collection of modules). It can be empty or contain initialization code and exports.MCQ 8
What does pip install requests do?
Answer: B
B is correct.
B is correct.
pip install downloads a package from the Python Package Index (PyPI) and installs it on your system. After installation, you can use import requests in your code.MCQ 9
What does json.dumps() do?
Answer: C
C is correct.
C is correct.
json.dumps() (dump string) converts a Python object (dict, list, etc.) to a JSON-formatted string. Option B describes json.loads(). Option A describes json.load().MCQ 10
Which command saves all installed package names and versions to a file?
Answer: C
C is correct.
C is correct.
pip freeze outputs installed packages in a format suitable for requirements.txt. The > redirects the output to a file. pip list shows packages in a human-readable table format, not the requirements format.MCQ 11
In which order does Python search for modules?
Answer: B
B is correct. Python searches: (1) the directory containing the running script, (2) directories in PYTHONPATH, (3) standard library directories, (4) site-packages (where pip installs). This is why naming a file after a standard library module causes shadowing.
B is correct. Python searches: (1) the directory containing the running script, (2) directories in PYTHONPATH, (3) standard library directories, (4) site-packages (where pip installs). This is why naming a file after a standard library module causes shadowing.
MCQ 12
What does random.shuffle(my_list) return?
Answer: C
C is correct.
C is correct.
random.shuffle() modifies the list in place and returns None. This is unlike random.sample(), which returns a new list. A common mistake is writing x = random.shuffle(my_list), which sets x to None.MCQ 13
What is the difference between a module and a package?
Answer: B
B is correct. A module is a single
B is correct. A module is a single
.py file. A package is a directory that contains an __init__.py file and one or more modules. Packages can also contain sub-packages (nested directories with their own __init__.py).MCQ 14
What happens when you import a module that has already been imported?
Answer: B
B is correct. Python caches imported modules in
B is correct. Python caches imported modules in
sys.modules. On subsequent imports, Python returns the cached module object without re-executing the file. This is why module-level code runs only once, even if the module is imported from multiple files.MCQ 15
What is a relative import in Python?
Answer: B
B is correct. Relative imports use dots:
B is correct. Relative imports use dots:
from .utils import helper (current package) or from ..parent import something (parent package). They only work inside packages. Absolute imports (full path from project root) are generally recommended for clarity.MCQ 16
Why is from module import * considered bad practice?
Answer: C
C is correct. Wildcard imports dump all public names from a module into your namespace. This makes it unclear where names come from, and if two modules define the same name, one silently overwrites the other. This leads to subtle, hard-to-find bugs.
C is correct. Wildcard imports dump all public names from a module into your namespace. This makes it unclear where names come from, and if two modules define the same name, one silently overwrites the other. This leads to subtle, hard-to-find bugs.
MCQ 17
What does dir() return when called without arguments?
Answer: B
B is correct.
B is correct.
dir() without arguments returns a list of names defined in the current local scope, including imported modules, variables, functions, and classes. dir(module) with an argument returns names defined in that module.MCQ 18
What converts a Python None value to when using json.dumps()?
Answer: B
B is correct. Python
B is correct. Python
None becomes JSON null. Other conversions: Python True/False become JSON true/false. Python tuples become JSON arrays. Python dicts become JSON objects.Coding Challenges
Challenge 1: Module Explorer
EasyWrite a function explore_module(module) that takes an imported module and returns a dictionary with three keys: 'name' (the module name), 'count' (number of public names), and 'functions' (list of public names that are callable). Test it with the math module.
Sample Input
(No input required)
Sample Output
Module: math
Public names: 45
First 5 callable: ['acos', 'acosh', 'asin', 'asinh', 'atan']
Use dir() to get names. Filter names starting with _ as non-public. Use callable() to check if a name refers to a function.
import math
def explore_module(module):
public_names = [n for n in dir(module) if not n.startswith('_')]
functions = [n for n in public_names if callable(getattr(module, n))]
return {
'name': module.__name__,
'count': len(public_names),
'functions': functions
}
result = explore_module(math)
print(f"Module: {result['name']}")
print(f"Public names: {result['count']}")
print(f"First 5 callable: {result['functions'][:5]}")Challenge 2: JSON Config Manager
EasyWrite two functions: save_config(filename, config_dict) that saves a dictionary to a JSON file with 2-space indentation, and load_config(filename, defaults) that loads a JSON file and merges it with a defaults dictionary (defaults are used for any missing keys).
Sample Input
(No input required)
Sample Output
Saved config to settings.json
Loaded: {'theme': 'dark', 'font_size': 14, 'language': 'en', 'auto_save': True}
Use json.dump and json.load. Handle FileNotFoundError in load_config.
import json
def save_config(filename, config_dict):
with open(filename, 'w') as f:
json.dump(config_dict, f, indent=2)
print(f"Saved config to {filename}")
def load_config(filename, defaults=None):
if defaults is None:
defaults = {}
try:
with open(filename, 'r') as f:
config = json.load(f)
except FileNotFoundError:
config = {}
merged = {**defaults, **config}
return merged
defaults = {'theme': 'light', 'font_size': 12, 'language': 'en', 'auto_save': True}
user_config = {'theme': 'dark', 'font_size': 14}
save_config('settings.json', user_config)
result = load_config('settings.json', defaults)
print(f"Loaded: {result}")Challenge 3: Random Password Generator
EasyWrite a function generate_password(length, include_digits=True, include_symbols=True) using the random module. The password must contain at least one lowercase letter, one uppercase letter, and (if enabled) one digit and one symbol. Shuffle the final result.
Sample Input
(No input required)
Sample Output
Password (12 chars): kA3$mN7xR!pQ
Password (8, no symbols): aB3nK8mR
Password (6, letters only): kRmNaB
Use random.choice for character selection and random.shuffle for mixing. Ensure minimum character type requirements are met.
import random
import string
def generate_password(length=12, include_digits=True, include_symbols=True):
if length < 4:
length = 4
password = []
password.append(random.choice(string.ascii_lowercase))
password.append(random.choice(string.ascii_uppercase))
pool = string.ascii_letters
if include_digits:
password.append(random.choice(string.digits))
pool += string.digits
if include_symbols:
password.append(random.choice('!@#$%&*'))
pool += '!@#$%&*'
remaining = length - len(password)
for _ in range(remaining):
password.append(random.choice(pool))
random.shuffle(password)
return ''.join(password)
random.seed(42)
print(f"Password (12 chars): {generate_password(12)}")
print(f"Password (8, no symbols): {generate_password(8, include_symbols=False)}")
print(f"Password (6, letters only): {generate_password(6, include_digits=False, include_symbols=False)}")Challenge 4: Date Calculator
MediumWrite a class DateCalculator with methods: days_between(date_str1, date_str2) that returns days between two dates in 'YYYY-MM-DD' format, add_days(date_str, days) that returns a new date string, and day_of_week(date_str) that returns the weekday name. Handle invalid date formats with a ValueError.
Sample Input
(No input required)
Sample Output
Days between 2026-01-01 and 2026-04-06: 95
Add 30 days to 2026-04-06: 2026-05-06
Day of week for 2026-04-06: Monday
Use datetime.strptime for parsing and strftime for formatting. Handle ValueError for bad date strings.
from datetime import datetime, timedelta
class DateCalculator:
DATE_FORMAT = '%Y-%m-%d'
def _parse(self, date_str):
try:
return datetime.strptime(date_str, self.DATE_FORMAT)
except ValueError:
raise ValueError(f"Invalid date format: {date_str}. Expected YYYY-MM-DD")
def days_between(self, date_str1, date_str2):
d1 = self._parse(date_str1)
d2 = self._parse(date_str2)
return abs((d2 - d1).days)
def add_days(self, date_str, days):
d = self._parse(date_str)
new_date = d + timedelta(days=days)
return new_date.strftime(self.DATE_FORMAT)
def day_of_week(self, date_str):
d = self._parse(date_str)
return d.strftime('%A')
calc = DateCalculator()
print(f"Days between 2026-01-01 and 2026-04-06: {calc.days_between('2026-01-01', '2026-04-06')}")
print(f"Add 30 days to 2026-04-06: {calc.add_days('2026-04-06', 30)}")
print(f"Day of week for 2026-04-06: {calc.day_of_week('2026-04-06')}")
try:
calc.days_between('2026-13-01', '2026-01-01')
except ValueError as e:
print(f"Error: {e}")Challenge 5: File Organizer Simulator
MediumWrite a function organize_files(file_list) that takes a list of filenames and returns a dictionary categorizing them by extension. Use os.path.splitext to extract extensions. Categories: 'images' (.jpg, .png, .gif), 'documents' (.pdf, .docx, .txt), 'code' (.py, .js, .html), 'other' (everything else). Also return a count summary.
Sample Input
(No input required)
Sample Output
images: ['photo.jpg', 'logo.png']
documents: ['report.pdf', 'notes.txt']
code: ['main.py', 'index.html']
other: ['data.csv']
Summary: images=2, documents=2, code=2, other=1
Use os.path.splitext. Handle files with no extension. Case-insensitive extension matching.
import os.path
def organize_files(file_list):
categories = {
'images': {'.jpg', '.jpeg', '.png', '.gif', '.bmp'},
'documents': {'.pdf', '.docx', '.doc', '.txt', '.xlsx'},
'code': {'.py', '.js', '.html', '.css', '.java', '.cpp'}
}
result = {'images': [], 'documents': [], 'code': [], 'other': []}
for filename in file_list:
_, ext = os.path.splitext(filename)
ext = ext.lower()
placed = False
for category, extensions in categories.items():
if ext in extensions:
result[category].append(filename)
placed = True
break
if not placed:
result['other'].append(filename)
return result
files = ['photo.jpg', 'main.py', 'report.pdf', 'logo.png', 'notes.txt', 'index.html', 'data.csv']
organized = organize_files(files)
for category, file_list in organized.items():
if file_list:
print(f"{category}: {file_list}")
summary = ', '.join(f"{k}={len(v)}" for k, v in organized.items())
print(f"Summary: {summary}")Challenge 6: Statistics Module
MediumCreate a module-like structure (using a class to simulate) called Statistics with methods: mean(data), median(data), mode(data), std_dev(data), and describe(data) which returns a summary dict. Use only the math module (do not use the statistics module). Include a __name__ guard to run tests.
Sample Input
(No input required)
Sample Output
Mean: 5.5
Median: 5.5
Mode: 3
Std Dev: 2.87
Summary: {'count': 10, 'mean': 5.5, 'median': 5.5, 'min': 1, 'max': 10, 'std_dev': 2.87}
Use math.sqrt for standard deviation. Handle edge cases (empty list, single element). Mode should return the most frequent value.
import math
class Statistics:
@staticmethod
def mean(data):
if not data:
return 0
return sum(data) / len(data)
@staticmethod
def median(data):
if not data:
return 0
sorted_data = sorted(data)
n = len(sorted_data)
mid = n // 2
if n % 2 == 0:
return (sorted_data[mid - 1] + sorted_data[mid]) / 2
return sorted_data[mid]
@staticmethod
def mode(data):
if not data:
return None
freq = {}
for x in data:
freq[x] = freq.get(x, 0) + 1
return max(freq, key=freq.get)
@staticmethod
def std_dev(data):
if len(data) < 2:
return 0
avg = sum(data) / len(data)
variance = sum((x - avg) ** 2 for x in data) / len(data)
return round(math.sqrt(variance), 2)
@staticmethod
def describe(data):
stats = Statistics
return {
'count': len(data),
'mean': stats.mean(data),
'median': stats.median(data),
'min': min(data),
'max': max(data),
'std_dev': stats.std_dev(data)
}
if __name__ == "__main__":
data = [1, 2, 3, 3, 4, 5, 6, 7, 8, 10]
stats = Statistics
print(f"Mean: {stats.mean(data)}")
print(f"Median: {stats.median(data)}")
print(f"Mode: {stats.mode(data)}")
print(f"Std Dev: {stats.std_dev(data)}")
print(f"Summary: {stats.describe(data)}")Challenge 7: Package Structure Validator
HardWrite a function validate_package(structure) that takes a nested dictionary representing a directory structure and checks if it is a valid Python package. A valid package must have __init__.py in each directory that is treated as a package. Return a list of issues found (missing __init__.py, empty packages, naming conflicts with standard library).
Sample Input
(No input required)
Sample Output
Issues found:
- Missing __init__.py in 'mypackage/utils/'
- Package name 'random' conflicts with standard library
- Empty package 'mypackage/empty/'
Use a recursive approach. Check names against a list of common standard library modules.
import sys
def validate_package(structure, path="", stdlib_modules=None):
if stdlib_modules is None:
stdlib_modules = {'os', 'sys', 'math', 'random', 'json', 'datetime',
'collections', 'itertools', 'functools', 'string',
'io', 'time', 're', 'pathlib', 'typing', 'abc'}
issues = []
for name, contents in structure.items():
current_path = f"{path}{name}/" if path else f"{name}/"
if isinstance(contents, dict):
if name in stdlib_modules:
issues.append(f"Package name '{name}' conflicts with standard library")
if '__init__.py' not in contents:
issues.append(f"Missing __init__.py in '{current_path}'")
sub_items = {k: v for k, v in contents.items() if k != '__init__.py'}
if not sub_items:
issues.append(f"Empty package '{current_path}'")
sub_dirs = {k: v for k, v in contents.items() if isinstance(v, dict)}
for sub_name, sub_contents in sub_dirs.items():
issues.extend(validate_package(
{sub_name: sub_contents}, current_path, stdlib_modules
))
return issues
package_structure = {
'mypackage': {
'__init__.py': None,
'core.py': None,
'utils': {
'helpers.py': None
},
'random': {
'__init__.py': None,
'generator.py': None
},
'empty': {
'__init__.py': None
}
}
}
issues = validate_package(package_structure)
if issues:
print("Issues found:")
for issue in issues:
print(f"- {issue}")
else:
print("Package structure is valid!")Challenge 8: Module Dependency Analyzer
HardWrite a function analyze_imports(code_string) that parses Python code (as a string) and extracts all import statements. Return a dictionary with 'standard' (standard library), 'third_party' (known third-party), and 'local' (assumed local) module names. Also detect potential circular import risks by finding mutual imports in a dict of module_name: code_string pairs.
Sample Input
(No input required)
Sample Output
standard: ['math', 'os', 'json']
third_party: ['requests', 'numpy']
local: ['my_utils', 'config']
Circular risk: module_a <-> module_b
Parse import and from...import statements using string operations. Categorize against a known list of standard library modules.
def analyze_imports(code_string):
stdlib = {'os', 'sys', 'math', 'random', 'json', 'datetime', 'collections',
'itertools', 'functools', 'string', 'io', 'time', 're', 'pathlib',
'typing', 'abc', 'csv', 'hashlib', 'logging', 'unittest', 'copy',
'pprint', 'textwrap', 'enum', 'dataclasses', 'contextlib'}
third_party = {'requests', 'numpy', 'pandas', 'flask', 'django', 'pytest',
'scipy', 'matplotlib', 'sqlalchemy', 'pillow', 'beautifulsoup4'}
imports = {'standard': [], 'third_party': [], 'local': []}
for line in code_string.strip().split('\n'):
line = line.strip()
module = None
if line.startswith('import '):
parts = line.replace('import ', '').split(',')
for part in parts:
module = part.strip().split(' as ')[0].split('.')[0]
if module in stdlib:
imports['standard'].append(module)
elif module in third_party:
imports['third_party'].append(module)
else:
imports['local'].append(module)
elif line.startswith('from '):
module = line.split(' ')[1].split('.')[0]
if module in stdlib:
imports['standard'].append(module)
elif module in third_party:
imports['third_party'].append(module)
elif not module.startswith('.'):
imports['local'].append(module)
for key in imports:
imports[key] = sorted(set(imports[key]))
return imports
def find_circular_risks(modules_code):
module_imports = {}
for name, code in modules_code.items():
result = analyze_imports(code)
module_imports[name] = result['local']
risks = []
checked = set()
for mod_a, deps_a in module_imports.items():
for mod_b, deps_b in module_imports.items():
if mod_a != mod_b and (mod_b, mod_a) not in checked:
if mod_b in deps_a and mod_a in deps_b:
risks.append((mod_a, mod_b))
checked.add((mod_a, mod_b))
return risks
code = """import math
import os
import json
import requests
import numpy as np
from datetime import datetime
from my_utils import helper
import config"""
result = analyze_imports(code)
for category, modules in result.items():
print(f"{category}: {modules}")
modules = {
'module_a': 'import module_b\nimport math',
'module_b': 'import module_a\nimport os',
'module_c': 'import module_a'
}
risks = find_circular_risks(modules)
for a, b in risks:
print(f"Circular risk: {a} <-> {b}")Need to Review the Concepts?
Go back to the detailed notes for this chapter.
Read Chapter NotesWant to learn Python with a live mentor?
Explore our Python course