Python Modules and Packages Quiz: Imports, venv and argparse
Test yourself: 12 questions and three programs on Python imports and sys.modules, packages and python -m, venv, pip and pyproject.toml, and argparse scripts.
- Course: Python study plan
- Module: Modules, packages and imports
- Kind: Checkpoint — cleared at 70%
- Reading time: 22 min
- Runtime: CPython 3.11
Checkpoint — Modules, packages and imports is the checkpoint that closes the Modules, packages and imports module: a graded quiz and whole-program exercises, passed at 70%.
Instructions
This checkpoint covers the whole module: what import does and the sys.modules cache, from-imports copying bindings, __name__ and circular imports, packages with __init__.py, relative imports and python -m, the standard-library map, virtual environments with pip and pyproject.toml, and command-line scripts with argparse, the three streams and exit codes.
How it works. Twelve questions and three programs. You need 70% on the questions and every program accepted to clear the module. You can retake it as often as you like; your best score counts.
Before you start, make sure you can answer these from memory:
- How many times does a module's top-level code run in one process, and why?
- After
from config import DEBUG, what does rebindingconfig.DEBUGdo to yourDEBUG? - What does
import shopdo aboutshop.models? - Why does
python shop/cli.pybreak relative imports, and what is the fix? - What is the difference between
requests>=2.31,<3inpyproject.tomlandrequests==2.31.0in a lock file? - Which stream do error messages go to, and what exit code does argparse use for bad usage?
- Where does a data file inside a package get opened from?
The three programs are a dependency resolver that orders modules by their imports and detects cycles, a requirements parser that checks installed versions against specifiers, and a command-line tool whose arguments are parsed by argparse from lines of input.
Common questions
How many times does a module's top-level code run in one process?
Once, at the first import anywhere in the process. The module object is then cached in sys.modules, and every later import of it is a dictionary lookup that binds the cached object, so top-level side effects such as printing or opening files never repeat.
After from config import DEBUG, does rebinding config.DEBUG change your DEBUG?
No. from config import DEBUG copied the binding at import time, so your DEBUG still refers to the old object after config.DEBUG is rebound. Read module-level state that changes through the module, as config.DEBUG, to see the new value.
What is the difference between requests>=2.31,<3 and requests==2.31.0?
requests>=2.31,<3 in pyproject.toml is a loose range for a direct dependency: any 2.x from 2.31 on, so the project can coexist with other packages. requests==2.31.0 in a lock file pins one exact version, so every deployment installs the same thing.
Exercises
Import graph
Read lines <module>: <imports…> (possibly none) and an entry module on the last line entry <name>. Compute the order in which module bodies finish executing when the entry is imported — a depth-first walk where each module's imports complete before it does, each module once — and print it. If the walk meets a module that is currently being imported (a cycle), print cycle: a -> b -> … -> a for the first cycle found, using the path from that module back to itself, and stop.
Input: lines, then entry <name>. Output: order: <names> or the cycle: line.
a: b c
b: c
c:
entry a
prints
order: c b aRequirements check
Requirements arrive as name<specifiers> lines and the installed set as name==version lines after a -- line. Specifiers are comma-separated op version pairs with ==, !=, >=, <=, >, <, or ~= (compatible release: ~=1.4 means >=1.4,<2; ~=1.4.2 means >=1.4.2,<1.5). Print each requirement's status and finish with problems <n> counting the missing and conflicting ones.
Input: lines, --, lines. Output: <name>: ok|conflict|missing per requirement, then problems <n>.
requests~=2.31
numpy>=1.26,<2
mypy
--
requests==2.32.1
numpy==2.0.0
prints
requests: ok
numpy: conflict
mypy: missing
problems 2An inventory command
Build a sub-command tool with argparse (exit_on_error=False): add name --qty N (default 1), remove name [--all] (removes one unit, or every unit with --all), show (prints name qty lines in name order, or empty). Each input line is a command line split with shlex.split; a usage error prints usage error; removing an unknown item prints unknown item. Keep the state across lines.
Input: command lines. Output: one line per show row, plus the error lines.
add bolt --qty 3
add nut
remove bolt
remove screw
show
remove nut --all
show
prints
unknown item
bolt 2
nut 1
bolt 2In this module: Modules, packages and imports
- Modules and imports — files, namespaces and sys.modules
- Packages — directories, __init__.py, relative imports and project layout
- The standard library map — where to look before you write it
- Virtual environments and packaging — venv, pip and pyproject.toml
- Scripts and the command line — argv, argparse, exit codes and streams
- Checkpoint — Modules, packages and imports (this lesson)
← Scripts and the command line — argv, argparse, exit codes and streams · math, statistics, fractions, decimal and random →