We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Parallel Python with Process Pools step 7 of 24
Audit a Library for Import-Time Side Effects
The article listed calls that a library should not make when it is imported. Write a checker that finds them in a library's source without running it, so CI can check every change.
audit_library("import logging\n\nlogging.basicConfig()\n")
# [("L003", 3, "logging.basicConfig")]
What to write
def audit_library(source: str) -> list[tuple[str, int, str]]:
Parse source with ast.parse, and let a SyntaxError propagate. Never
run the source. Return one (code, line, detail) tuple per finding:
| Code | Finds | Where |
|---|---|---|
L001 |
A call whose last name is set_start_method |
Every call in the source, including function bodies and annotations |
L002 |
A call whose last name is ProcessPoolExecutor, ThreadPoolExecutor, InterpreterPoolExecutor or Pool |
Import-time code |
L003 |
A call whose last name is basicConfig |
Import-time code |
L004 |
A call to exactly signal.signal |
Import-time code |
L005 |
A call to exactly os.environ.update, os.environ.setdefault or os.putenv, or an assignment to os.environ[...] |
Import-time code |
Names
- Build a call's dotted name from
ast.Nameandast.Attributenodes only. The last name ofmultiprocessing.set_start_methodisset_start_method. A barePool()counts. - A call such as
factory().Pool()has no dotted name, so it matches nothing. detailis the call's full dotted name, or"os.environ"for an assignment.- Match names only. Don't follow imports, resolve aliases such as
import os as o, or look inside a function to see what it calls.
Import-time code
Import-time code is everything in the source except these parts:
- The bodies of functions, async functions and lambdas.
- Annotations, type parameters such as the
[T]indef first[T], andtypealias statements. Python 3.14 does not evaluate them at import.
These parts count as the code around them, not as a body:
- A function's decorators and default values, and a lambda's default values.
- A class body, with the class's decorators, bases and keyword arguments. A class at the top level is import-time code, and a class inside a function is not.
Scan comprehensions and generator expressions like any other code. Every
branch counts, including if __name__ == "__main__": and code that can
never run.
Assignments to os.environ
- Check plain, augmented and annotated assignments, such as
os.environ["A"] += "1". - Look inside tuple, list and starred targets. Report one finding per
os.environ[...]target, with the assignment statement's line number. - An annotated assignment with no value, such as
os.environ["A"]: str, assigns nothing, so it is not an assignment finding. Still check the calls inside its target. del os.environ["A"]and other methods such asos.environ.popare not findings.
Output
- Use the call's own line number for a call finding.
- Sort the findings by line, then code, then detail.
- Keep duplicates. Two calls that give the same tuple are two findings.
L001 applies even with force=True, because the library still overrides
the application's choice.
Your submission must pass mypy --strict.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.