Python Module 6 – Modules, packages and the standard library
A tour of the Python standard library
Find the standard module for everyday jobs, read the library reference with its availability and version notes, and spot the modules Python removed.
What you will learn
- Find the standard module for an everyday job, such as matching a typo or checking an address
- Read a module's page for its version, availability and security notes
- Check whether a standard module works on the platform where your code runs
- Replace an import of a module that Python 3.12 or 3.13 removed
- Run standard modules as commands with python -m, keeping http.server on your own computer
Before you start
What you’ll learn · Before you start
What you will learn
- Find the standard module for an everyday job, such as matching a typo or checking an address
- Read a module's page for its version, availability and security notes
- Check whether a standard module works on the platform where your code runs
- Replace an import of a module that Python 3.12 or 3.13 removed
- Run standard modules as commands with python -m, keeping http.server on your own computer
Before you start
On this page
Python 3.14.8 lists 297 module names in sys.stdlib_module_names, 194 of them without a leading underscore, and every
one of them comes with Python itself. That set is the standard library: The modules that come with Python itself, such as json, pathlib and sqlite3, documented in the library reference. sys.stdlib_module_names lists their names for the Python that runs, whether or not each one works there.: install
Python 3.14 and import json, import pathlib or import sqlite3 work straight away, with nothing to download.
Nobody learns all of it, and nobody needs to. What pays off is a rough map of what is there, so that you look for a module before you write the code yourself or install a package, and the habit of reading two kinds of note on a module’s page: in which version something appeared or changed, and on which platforms it works. This lesson gives you the map, runs ten modules in ten lines, shows which modules recent versions removed, and ends with modules that also work as commands.
The library has a module for many everyday jobs
The library reference sorts its modules into about thirty chapters by topic, from Text Processing Services to
Unix-specific services, and some of its modules are packages with modules of their own, such as email, xml and
concurrent. This table follows the jobs you meet first instead, with the modules to try for each:
| Job | Start with | One thing it does |
|---|---|---|
| Work with text | string, re, textwrap, difflib, unicodedata |
re.findall(r"\d+", text) lists every number in a text |
| Organise data | collections, heapq, bisect, enum, dataclasses, itertools |
collections.Counter(words) counts each word |
| Calculate | math, decimal, fractions, statistics, random |
statistics.median(marks) finds the middle value |
| Handle dates and times | datetime, zoneinfo, time |
zoneinfo.ZoneInfo("Asia/Kolkata") is a time zone with its rules |
| Use files and folders | pathlib, shutil, tempfile, glob |
pathlib.Path("data").glob("*.csv") finds the CSV files of a folder |
| Read and write formats | csv, json, tomllib, sqlite3, zipfile |
tomllib.load() reads a pyproject.toml |
| Compress | zlib, gzip, bz2, lzma, compression.zstd |
gzip.open() reads a .gz file as if it were a plain one |
| Protect secrets and data | hashlib, hmac, secrets |
secrets.token_urlsafe() makes an unguessable token |
| Talk to the system | os, sys, subprocess, logging, argparse |
subprocess.run() starts another program and waits for it |
| Use the network | urllib.parse, urllib.request, http, email, ipaddress |
urllib.parse.urlencode() builds a query string |
| Do several things at once | threading, multiprocessing, concurrent.futures, asyncio |
concurrent.futures runs a function over many inputs in a pool |
| Test and measure | unittest, doctest, pdb, timeit |
timeit measures how long a small piece of code takes |
Here are ten small jobs in ten lines, each done by a different module, and every one of those modules is already on your computer if Python is:
"""Ten everyday jobs, each done by a different module of the standard library."""
import collections
import difflib
import hashlib
import ipaddress
import json
import pathlib
import statistics
import textwrap
import unicodedata
import urllib.parse
sentence = "The standard library ships with every copy of Python."
jobs = [
("textwrap", textwrap.shorten(sentence, width=36, placeholder=" ...")),
("difflib", difflib.get_close_matches("pirnt", ["print", "input", "point", "sprint"])),
("collections", collections.Counter("mississippi").most_common(2)),
("statistics", statistics.median([72, 85, 64, 91])),
("json", json.dumps({"name": "Asha", "marks": [92, 88]}, sort_keys=True)),
("pathlib", pathlib.PurePosixPath("reports/marks.csv").with_suffix(".json").as_posix()),
("urllib.parse", urllib.parse.urlencode({"q": "python modules", "page": 2})),
("hashlib", hashlib.sha256(b"hello").hexdigest()[:16]),
("ipaddress", ipaddress.ip_address("192.168.1.20").is_private),
("unicodedata", unicodedata.name("₹")),
]
for module, result in jobs:
print(f"{module:<13}{result!r}") Output
textwrap 'The standard library ships with ...'
difflib ['print', 'point', 'sprint']
collections [('i', 4), ('s', 4)]
statistics 78.5
json '{"marks": [92, 88], "name": "Asha"}'
pathlib 'reports/marks.json'
urllib.parse 'q=python+modules&page=2'
hashlib '2cf24dba5fb0a30e'
ipaddress True
unicodedata 'INDIAN RUPEE SIGN'
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 one_liners.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
textwrap.shorten()collapsed the spaces, cut the sentence at a word boundary and added the marker, so the result fits in 36 characters, a job people often write by hand with slicing that cuts words in half.difflib.get_close_matches()ranked the candidates by their similarity to the typopirnt, best first, keeping those above its default cutoff of 0.6. It is the “Did you mean…?” of many command-line tools. Press Edit, change"pirnt"to"imput"and run it again: the only suggestion left isinput.Counter.most_common(2)found the two most frequent letters.iandsboth occur four times, and equal counts keep the order in which the letters first appeared.ipaddressknows the address blocks that are set aside for private networks, so192.168.1.20is private. A text test such asaddress.startswith("192.168.")would get10.0.0.5and172.16.0.1wrong, and both are private too.hashlib.sha256()gives the same 64 hexadecimal digits for the same bytes on every computer; the example prints the first 16.unicodedata.name()gives the official Unicode name of a character, here the rupee sign.
Checkpoint
Check: A standard module for each everyday job
Every module page has the same five parts
Every module has a page in the library reference, and the pages share one layout. Knowing it makes the library quicker to use than any list of modules:
- The heading and summary, such as “csv — CSV File Reading and Writing”, and for modules written in Python a
Source code link (
Lib/csv.py). The source is ordinary Python, and reading it is a good way to settle what a function really does. - The functions and classes, each with its parameters, what it returns and what it raises, and on most pages examples at the end.
- Version notes under an entry: “Added in version 3.11”, “Changed in version 3.14”, “Deprecated since version
3.13”. Compare them with the version you run (
python --version): code written for 3.14 may use something that a 3.10 installation does not have. - availability note: A line on a page of the library reference, such as Availability: POSIX, not WASI, not Android, not iOS, that says on which platforms a function or a module exists., such as “Availability: POSIX, not WASI, not Android,
not iOS.” under
os.fork(). They say where a function or a module exists at all. - Warnings and “See also” boxes. Security warnings matter most: the
picklepage warns that the module is not secure and that you should only unpickle data you trust, and thehttp.serverpage says it is not recommended for production.
The flowchart turns the two kinds of note into two questions to answer before you rely on a module, here for the job of reading a CSV file:
Finding a standard module and checking it before you use it
Text description of the diagram
The flowchart reads from top to bottom.
- It starts with a job to do, for example reading a CSV file.
- Next, the library reference: the chapter for the topic (here File Formats, which holds csv), the module index or the search box.
- That leads to the module's page, with its summary, a link to its source code, and its functions and examples.
- First check, the availability note: does the module work where the code will run? If not, use another standard module or a package from PyPI.
- Second check, the version notes (Added in, Changed in, Deprecated since): does the Python you run have what the page describes? If not, again choose another module or a package from PyPI.
- When both answers are yes, use the module.
To reach a page, open the chapter for the topic, the alphabetical module index (the “modules” link at the top of
every page of the documentation) or the search box. Without a network, help("csv") at the interactive prompt shows
the module’s own documentation strings.
Checkpoint
Check: Reading a module's page
A listed module may still be missing where your code runs
The library’s introduction explains the availability notes. “Availability: Unix” marks a function that Unix systems usually have, and unless the note says otherwise it covers macOS, iOS and Android as well, which are all Unix-like underneath. Each “not” takes a platform away again. Two groups of platforms lose the most:
- A portable format for compiled programs that runs inside a browser or a runtime such as wasmtime. CPython can be compiled to it, with only part of the operating system's interface.,
where Python runs inside a browser or a runtime such as wasmtime. The Emscripten and WASI builds have only a subset
of the operating system’s interface, so modules that start processes, use threads, open network connections or
send signals are missing or behave differently, and
subprocesscan be imported but does not work. - Android and iOS apps, which embed Python. They have no terminal, so
cursesandreadlineare not available, and an iOS app cannot start a subprocess at all.
The runner on these pages belongs to the first group. It uses Pyodide, which is CPython compiled for Emscripten, and
Pyodide also leaves out modules that could not work there or would only make its download bigger, such as tkinter,
curses and venv. This program asks the Python that runs it what works:
"""Which standard modules can this Python import?
And do the ones that need the operating system work?"""
import importlib
import subprocess
import sys
import threading
MODULES = [
"sqlite3", "zoneinfo", "compression.zstd", "tkinter", "curses", "venv",
"concurrent.interpreters",
]
names = sys.stdlib_module_names
public = [name for name in names if not name.startswith("_")]
print(len(names), "names in sys.stdlib_module_names,", len(public), "without a leading underscore")
for name in MODULES:
try:
importlib.import_module(name)
print(f"import {name}: works")
except ImportError as error:
print(f"import {name}: {type(error).__name__}")
def attempt(action):
"""'works', or the kind of error the action raised."""
try:
action()
return "works"
except (OSError, RuntimeError) as error:
return f"fails with {type(error).__name__}"
def run_program():
subprocess.run([sys.executable, "-c", "pass"], check=True)
def start_thread():
worker = threading.Thread(target=lambda: None)
worker.start()
worker.join()
print("subprocess.run():", attempt(run_program))
print("Thread.start():", attempt(start_thread)) Output
297 names in sys.stdlib_module_names, 194 without a leading underscore import sqlite3: works import zoneinfo: works import compression.zstd: works import tkinter: works import curses: works import venv: works import concurrent.interpreters: works subprocess.run(): works Thread.start(): works
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 available.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Version note
The recorded output comes from CPython 3.14.8 on macOS, where every import and both calls work. Press Run in the browser and four imports fail with ModuleNotFoundError, subprocess.run() fails with OSError because a browser cannot start programs, and Thread.start() fails with RuntimeError because the runner has no threads. The first line stays the same.
In your browser, Pyodide 314.0.7 (CPython 3.14.2) prints:
297 names in sys.stdlib_module_names, 194 without a leading underscore import sqlite3: works import zoneinfo: works import compression.zstd: works import tkinter: ModuleNotFoundError import curses: ModuleNotFoundError import venv: ModuleNotFoundError import concurrent.interpreters: ModuleNotFoundError subprocess.run(): fails with OSError Thread.start(): fails with RuntimeError
The same program, run in two places, gives two answers. Side by side:
| What the program tried | CPython 3.14.8 on macOS | The browser runner (Pyodide) |
|---|---|---|
Count sys.stdlib_module_names |
297, 194 without a leading underscore | the same |
import sqlite3, zoneinfo, compression.zstd |
works | works |
import tkinter, curses, venv |
works | ModuleNotFoundError |
import concurrent.interpreters |
works | ModuleNotFoundError |
subprocess.run() |
works | fails with OSError |
Thread.start() |
works | fails with RuntimeError |
Two details of that output are worth keeping. sys.stdlib_module_names names every standard module of that version
of Python, whether or not it can be imported where you are, so 297 is printed in the browser too; the only test of
whether a module works is to import it. And the standard library you have is not always complete even on a laptop:
on Unix-like systems Python often comes as a set of packages of the operating system, and an optional part such as
tkinter may need one more package from the system’s package manager before import tkinter works.
Key idea
A name in sys.stdlib_module_names belongs to that version of Python; whether the module works is settled only by
importing and using it where the code runs.
Checkpoint
Check: Where a module works
Python removes old modules after warning for two releases
Python also takes modules away. Its compatibility policy, PEP 387, asks for a deprecation: Notice that a feature will be removed in a later version, given in the documentation and usually by a DeprecationWarning. Python's compatibility policy, PEP 387, asks for such a warning in at least two releases before a removal. warning in at least two feature releases, such as 3.11 and 3.12, before something is removed. Walk through the releases that changed the list of modules this lesson uses:
- 3.11
tomllib joins the library added
tomllib reads TOML files such as pyproject.toml. It cannot write them, and code that must also run on older versions installs the tomli package from PyPI instead.
- 3.12
distutils and four other modules are removed removed
distutils, the old packaging library, goes (PEP 632), and with it imp, asynchat, asyncore and smtpd. Code that imports them stops with ModuleNotFoundError; importlib replaces imp, and asyncio replaces asyncore.
- 3.13
19 old modules are removed at once removed
PEP 594 takes out the "dead batteries", among them cgi, cgitb, crypt, pipes, telnetlib, nntplib, imghdr and audioop. lib2to3, the 2to3 tool and tkinter.tix go in the same release.
- 3.14
Four new modules added
annotationlib, compression with its compression.zstd, concurrent.interpreters and string.templatelib arrive. The next section runs three of them.
The timeline has 4 events, from 3.11 to 3.14.
Python 3.12 removed distutils, the old packaging library (PEP 632), together with imp, asynchat, asyncore and
smtpd. Python 3.13 removed 19 modules at once, the “dead batteries” of PEP 594, among them cgi, cgitb, crypt,
pipes, telnetlib, nntplib, imghdr and audioop, and also lib2to3, the 2to3 tool and tkinter.tix. Code
from an old tutorial that imports one of them now stops at once with ModuleNotFoundError. This program tries eight
of those imports and prints what to use instead:
"""Modules that older tutorials import, and what to use instead on Python 3.14."""
import importlib
INSTEAD = {
"distutils": ("3.12", "setuptools, or sysconfig, shutil.which() and subprocess.run()"),
"imp": ("3.12", "importlib"),
"asyncore": ("3.12", "asyncio"),
"cgi": ("3.13", "urllib.parse for query strings, email.message for headers"),
"crypt": ("3.13", "hashlib, or a password-hashing package such as argon2-cffi"),
"pipes": ("3.13", "subprocess, and shlex.quote()"),
"mailcap": ("3.13", "mimetypes"),
"telnetlib": ("3.13", "telnetlib3 or Exscript from PyPI"),
}
for name, (version, advice) in INSTEAD.items():
try:
importlib.import_module(name)
print(f"{name}: still in the standard library")
except ModuleNotFoundError:
print(f"{name}: removed in {version}; use {advice}") Output
distutils: removed in 3.12; use setuptools, or sysconfig, shutil.which() and subprocess.run() imp: removed in 3.12; use importlib asyncore: removed in 3.12; use asyncio cgi: removed in 3.13; use urllib.parse for query strings, email.message for headers crypt: removed in 3.13; use hashlib, or a password-hashing package such as argon2-cffi pipes: removed in 3.13; use subprocess, and shlex.quote() mailcap: removed in 3.13; use mimetypes telnetlib: removed in 3.13; use telnetlib3 or Exscript from PyPI
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 removed.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
The library reference keeps a chapter called Removed Modules, with a page for each module and its replacement. For
most of the modules removed in 3.13 the release notes also name a copy published on PyPI, such as
standard-telnetlib. Such a copy keeps old code running, but new code should use the replacement.
Checkpoint
Check: Modules that were removed
Python 3.14 added four modules
Version 3.14 adds four modules:
annotationlibreads annotations (PEP 749). Since 3.14, Python evaluates annotations only when something asks for them, so a type hint may name a class that is defined further down the file.compressionis a package that gathers the compression modules, and its newcompression.zstdhandles the Zstandard format (PEP 784).concurrent.interpretersruns Python code in several interpreters inside one process (PEP 734). The browser runner does not have it, as the program above showed.string.templatelibholds the types behind template strings, the new A string literal with t before its opening quote, new in Python 3.14. It makes a Template that keeps the fixed text and the values apart, instead of a str. literals (PEP 750).
"""Three of the modules that are new in Python 3.14, at work."""
import annotationlib
import bz2
import lzma
import zlib
from compression import zstd
from string.templatelib import Template
# compression.zstd: Zstandard, next to the older zlib, bz2 and lzma.
# The data: 500 copies of one line of a CSV file.
data = b"92,Asha\n" * 500
for module in (zstd, zlib, bz2, lzma):
packed = module.compress(data)
assert module.decompress(packed) == data
print(f"{module.__name__:<17}{len(data)} bytes -> {len(packed)} bytes")
# string.templatelib: a t-string keeps its fixed text and its values apart.
name = "Asha"
greeting = t"Hello, {name}!"
print("t-string:", type(greeting) is Template, greeting.strings, greeting.values)
# annotationlib: annotations are evaluated only when something asks for them,
# so a class that is defined further down is no error.
def best_mark(student: Student) -> int:
return max(student.marks)
hints = annotationlib.get_annotations(best_mark, format=annotationlib.Format.STRING)
print("annotations:", hints)
class Student:
marks = [92, 88, 95]
print("now evaluated:", annotationlib.get_annotations(best_mark)["student"] is Student)
print("best mark:", best_mark(Student())) Output
compression.zstd 4000 bytes -> 25 bytes
zlib 4000 bytes -> 43 bytes
bz2 4000 bytes -> 66 bytes
lzma 4000 bytes -> 100 bytes
t-string: True ('Hello, ', '!') ('Asha',)
annotations: {'student': 'Student', 'return': 'int'}
now evaluated: True
best mark: 95
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 new_in_314.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
- On 4,000 bytes of very repetitive text, Zstandard produced 25 bytes, against 43 for
zlib, 66 forbz2and 100 forlzma. Real files compress far less. PEP 784 argues for Zstandard on balance: its output is clearly smaller than that of zlib or bzip2, and it unpacks much faster than LZMA. - The t-string did not become a
str. ATemplatekeeps its fixed text (strings) apart from its values (values), so that a library can escape the values for HTML or SQL before it joins them, which an f-string never allows. get_annotations()read the hintStudentas text while no class of that name existed, and as the class itself once it did.
Checkpoint
Check: The new modules of Python 3.14
Many standard modules also run as commands
python -m module runs a module as a program, and the library reference lists 50 modules that have a command-line
interface. This program runs three of them, json on two small files, and shows what each command printed:
Python · cli/cli.py
"""Standard modules as command-line tools: each command, then what it printed."""
import subprocess
import sys
def run(*args):
print("$ python", *args)
result = subprocess.run([sys.executable, *args], capture_output=True, text=True)
print(result.stdout, end="")
if result.returncode:
print(result.stderr.strip().splitlines()[-1], f"(exit status {result.returncode})")
run("-m", "json", "student.json")
run("-m", "json", "--sort-keys", "--compact", "student.json")
run("-m", "json", "broken.json")
run("-m", "uuid", "-u", "uuid5", "-n", "@url", "-N", "https://example.com/")
run("-m", "mimetypes", "marks.csv", "report.pdf") Output
$ python -m json student.json
{
"name": "Asha",
"marks": [
92,
88,
95
],
"city": "Pune"
}
$ python -m json --sort-keys --compact student.json
{"city":"Pune","marks":[92,88,95],"name":"Asha"}
$ python -m json broken.json
Expecting ',' delimiter: line 1 column 17 (char 16) (exit status 1)
$ python -m uuid -u uuid5 -n @url -N https://example.com/
dd2c1780-811a-5296-81c5-178a0ef488bc
$ python -m mimetypes marks.csv report.pdf
type: text/csv encoding: None
type: application/pdf encoding: None
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 cli.py
cli/student.json
{"name": "Asha", "marks": [92, 88, 95], "city": "Pune"} cli/broken.json
{"name": "Ravi" "marks": [71, 64, 80]} python -m jsonchecks a JSON file and prints it indented. The short name is new in 3.14; older versions spell itpython -m json.tool, which still works.--sort-keyssorts the keys and--compactdrops the spaces.- On
broken.jsonit named the line and column where a comma is missing and ended with exit status 1, so a shell script or a CI step can use it as a check. python -m uuid, a command since 3.12, makes a UUID. Version 5 is computed from a namespace and a name, so it prints the same value on every computer, while the default, version 4, is random. Python 3.14 added versions 6, 7 and 8, and-Cto make several at once.python -m mimetypes, a public command since 3.14, guesses a file’s type from its name.
Others worth knowing are python -m venv .venv for a virtual environment, python -m zipfile -l archive.zip to list
an archive, python -m timeit to time a snippet, python -m sqlite3 marks.db for an SQLite shell, and
python -m unittest and python -m pdb for tests and the debugger.
Keep python -m http.server on your own computer
python -m http.server serves the files of the current folder on port 8000, which is handy for looking at a page
you are building. By default it listens on every network interface, so anyone who can reach your computer, on the
same Wi-Fi for example, can read every file in that folder. Add --bind 127.0.0.1 to keep it to your own computer,
and never use it for a real site: its documentation says that it only implements basic security checks.
Checkpoint
Check: Standard modules as commands
Practise: a scavenger hunt
Each function of the exercise names the module that does its job. The work is finding the right function on that module’s page, and the sample tests also read your file to check that every function really uses its module.
Exercise · Easy · Python
A scavenger hunt through the standard library
hunt.py has ten small functions, and each docstring names the standard module that does the job. Write each body with that module: find the function you need on the module's page of the library reference, then call it. Every module is already imported at the top of the file.
shorten_title(title, width): the title cut at a word boundary to at mostwidthcharacters, ending in...when something was cut, with runs of spaces collapsed (textwrap).median_mark(marks): the middle mark, or the mean of the two middle marks for an even count (statistics).new_ticket_id(): a new random identifier as a string of 36 characters, such as"3f1c9a2e-8d4b-4e6f-9a0b-1c2d3e4f5a6b"(uuid, version 4).did_you_mean(word, commands): the one command closest to a mistyped word, orNonewhen none is close (difflib).top_words(text, n): thenmost common words of the text, ignoring case, as(word, count)pairs, most common first (collections).extension(path): the file extension of a path in lower case, with its dot, such as".pdf", or""when there is none (pathlib).query_value(url, key): the first value of a query parameter of a URL, decoded, orNonewhen the URL does not have that parameter (urllib.parse).fingerprint(text): the SHA-256 hash of the text's UTF-8 bytes as 64 hexadecimal digits (hashlib).is_private(address):Truefor an address of a private network, such as192.168.1.20(ipaddress).pretty(data): the data as JSON text, indented by 2 spaces, with the keys sorted (json).
The sample tests import your file as hunt and also read it, to check that each function really uses its module.
Starter code · hunt.py
"""Ten small jobs, each done with one module of the standard library."""
import collections
import difflib
import hashlib
import ipaddress
import json
import pathlib
import statistics
import textwrap
import urllib.parse
import uuid
def shorten_title(title, width):
"""The title cut to at most `width` characters at a word boundary, ending in "..." when cut (textwrap)."""
return title
def median_mark(marks):
"""The middle mark, or the mean of the two middle marks (statistics)."""
return marks[0]
def new_ticket_id():
"""A new random identifier, as a string of 36 characters (uuid, version 4)."""
return ""
def did_you_mean(word, commands):
"""The command closest to a mistyped word, or None when nothing is close (difflib)."""
return None
def top_words(text, n):
"""The n most common words, ignoring case, as (word, count) pairs, most common first (collections)."""
return []
def extension(path):
"""The extension of a path in lower case, with its dot (".pdf"), or "" when there is none (pathlib)."""
return ""
def query_value(url, key):
"""The first value of a query parameter of a URL, decoded, or None when it is missing (urllib.parse)."""
return None
def fingerprint(text):
"""The SHA-256 hash of the text's UTF-8 bytes, as 64 hexadecimal digits (hashlib)."""
return ""
def is_private(address):
"""True for an address of a private network, such as 192.168.1.20 (ipaddress)."""
return False
def pretty(data):
"""The data as JSON text, indented by 2 spaces, keys sorted (json)."""
return str(data) The sample tests · test_hunt.py
import ast
import pathlib
import uuid
import hunt
# Each function of hunt.py and the module it must use.
MODULES = {
"shorten_title": "textwrap",
"median_mark": "statistics",
"new_ticket_id": "uuid",
"did_you_mean": "difflib",
"top_words": "collections",
"extension": "pathlib",
"query_value": "urllib.parse",
"fingerprint": "hashlib",
"is_private": "ipaddress",
"pretty": "json",
}
def imported_names(tree):
"""Each name that an import in the file binds, and the dotted name it stands for."""
names = {}
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
if alias.asname:
names[alias.asname] = alias.name
else:
top = alias.name.split(".")[0]
names[top] = top
elif isinstance(node, ast.ImportFrom) and node.module and not node.level:
for alias in node.names:
names[alias.asname or alias.name] = node.module + "." + alias.name
return names
def dotted(node):
""""urllib.parse.urlsplit" for the expression urllib.parse.urlsplit; None for anything else."""
parts = []
while isinstance(node, ast.Attribute):
parts.append(node.attr)
node = node.value
if not isinstance(node, ast.Name):
return None
parts.append(node.id)
return ".".join(reversed(parts))
def uses_module(function, module):
"""Whether the function's body refers to the module, or to a name imported from it."""
tree = ast.parse(pathlib.Path("hunt.py").read_text(encoding="utf-8"))
names = imported_names(tree)
for node in tree.body:
if isinstance(node, ast.FunctionDef) and node.name == function:
for inner in ast.walk(node):
text = dotted(inner) if isinstance(inner, (ast.Name, ast.Attribute)) else None
if not text:
continue
first, _, rest = text.partition(".")
if first in names:
full = names[first] + ("." + rest if rest else "")
if full == module or full.startswith(module + "."):
return True
return False
def test_shorten_title():
"""shorten_title cuts at a word boundary and ends in ..."""
assert hunt.shorten_title("A tour of the Python standard library", 20) == "A tour of the..."
assert hunt.shorten_title(" Python modules ", 20) == "Python modules"
def test_median_mark():
"""median_mark gives the middle value"""
assert hunt.median_mark([72, 85, 64, 91]) == 78.5
assert hunt.median_mark([3, 1, 2]) == 2
def test_new_ticket_id():
"""new_ticket_id gives a different version 4 UUID each time"""
first, second = hunt.new_ticket_id(), hunt.new_ticket_id()
assert isinstance(first, str) and len(first) == 36
assert uuid.UUID(first).version == 4
assert first != second
def test_did_you_mean():
"""did_you_mean finds the closest command, or None"""
assert hunt.did_you_mean("pirnt", ["print", "input", "exit"]) == "print"
assert hunt.did_you_mean("xyz", ["print", "input"]) is None
def test_top_words():
"""top_words counts words without regard to case"""
assert hunt.top_words("the cat and the hat and THE bat", 2) == [("the", 3), ("and", 2)]
def test_extension():
"""extension gives the last suffix in lower case"""
assert hunt.extension("reports/Term-2/Marks.CSV") == ".csv"
assert hunt.extension("archive.tar.gz") == ".gz"
assert hunt.extension("README") == ""
def test_query_value():
"""query_value decodes a parameter, or gives None"""
url = "https://example.com/search?q=python+modules&page=2"
assert hunt.query_value(url, "q") == "python modules"
assert hunt.query_value(url, "page") == "2"
assert hunt.query_value(url, "lang") is None
def test_fingerprint():
"""fingerprint is the SHA-256 of the UTF-8 bytes"""
assert hunt.fingerprint("hello") == "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
assert hunt.fingerprint("₹") == "d8c3e87cd7f5b7d388f9dc1e35ccee09640ef3dca63d449d9ef59fc323a87a20"
def test_is_private():
"""is_private knows private networks from public ones"""
assert hunt.is_private("192.168.1.20") is True
assert hunt.is_private("10.0.0.5") is True
assert hunt.is_private("8.8.8.8") is False
def test_pretty():
"""pretty indents by 2 spaces and sorts the keys"""
assert hunt.pretty({"name": "Asha", "marks": [92, 88]}) == '{\n "marks": [\n 92,\n 88\n ],\n "name": "Asha"\n}'
def test_each_function_uses_its_module():
"""every function uses the module its docstring names"""
missing = [f"{function} ({module})" for function, module in MODULES.items() if not uses_module(function, module)]
assert missing == [] A hint
Open the library reference page of each module and read its list of functions before you write any code: every job here is one call, sometimes followed by picking an item from the result. For example, difflib.get_close_matches() returns a list, which is empty when nothing is close, and urllib.parse.parse_qs() needs only the query part of the URL, which urllib.parse.urlsplit() gives you.
Results of the sample tests
| Test | Result | Details |
|---|
What your code printed
The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.
Sixteen short questions on the six parts of the tour come next, one at a time. The session leads with the part you have answered least well so far, and the reason behind each choice appears once you check it:
Practice that adapts to you
Practise this lesson
16 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Fresher · What is the standard library, and how do you tell whether a module belongs to it?
The standard library is the set of modules that is distributed with Python itself and documented in the library
reference, such as json, pathlib, sqlite3 and asyncio, so it is there wherever that Python is installed,
with nothing to install from PyPI. To check a name, look it up in the library reference’s module index, or ask the
interpreter: "tomllib" in sys.stdlib_module_names is True on Python 3.11 and newer. A good answer adds two
cautions. Being listed does not mean that a module works everywhere: availability notes, WebAssembly builds and
mobile apps leave parts out, and some Linux systems package parts such as tkinter separately. And the list
changes between versions: 3.12 and 3.13 removed old modules such as distutils and telnetlib, while 3.14 added
compression.zstd.
Key takeaways
- The standard library ships with Python: 297 top-level module names in Python 3.14.8, sorted by topic in the library reference, and worth searching before you write code or install a package.
- Modules such as
difflib,ipaddress,textwrapandunicodedatado jobs that people often write by hand. - On a module’s page, read the version notes, the availability notes and the warnings before you rely on it.
- Being listed in
sys.stdlib_module_namesdoes not mean a module works where you run it: WebAssembly, Android and iOS lack parts of the library, and the browser runner here has no workingsubprocessand no threads. - Python 3.12 removed
distutils,impandasyncore, 3.13 removed 19 old modules such ascgi,cryptandtelnetlib, and 3.14 addedannotationlib,compression.zstd,concurrent.interpretersandstring.templatelib. - Many modules are also commands, such as
python -m json,python -m uuidandpython -m venv, andpython -m http.serverbelongs on your own computer, with--bind 127.0.0.1.
Terms in this lesson
- availability note
- A line on a page of the library reference, such as Availability: POSIX, not WASI, not Android, not iOS, that says on which platforms a function or a module exists.
- deprecation
- Notice that a feature will be removed in a later version, given in the documentation and usually by a DeprecationWarning. Python's compatibility policy, PEP 387, asks for such a warning in at least two releases before a removal.
- standard library
- The modules that come with Python itself, such as json, pathlib and sqlite3, documented in the library reference. sys.stdlib_module_names lists their names for the Python that runs, whether or not each one works there.
References
- The Python Standard Library (Python Software Foundation)
- The Python Tutorial: Brief tour of the standard library (Python Software Foundation)
- Introduction: notes on availability (Python Software Foundation)
- Introduction: WebAssembly platforms (Python Software Foundation)
- sys.stdlib_module_names (Python Software Foundation)
- Removed Modules (Python Software Foundation)
- What’s New In Python 3.14: New modules (Python Software Foundation)
- tomllib: Parse TOML files (Python Software Foundation)
- zoneinfo: IANA time zone support (Python Software Foundation)
- Modules command-line interface (CLI) (Python Software Foundation)
- json: command-line interface (Python Software Foundation)
- uuid: command-line usage (Python Software Foundation)
- http.server: HTTP servers (Python Software Foundation)
- PEP 594: Removing dead batteries from the standard library (Python Software Foundation)
- PEP 632: Deprecate distutils module (Python Software Foundation)
- PEP 387: Backwards Compatibility Policy (Python Software Foundation)
- PEP 784: Adding Zstandard to the standard library (Python Software Foundation)
- Pyodide: Python standard library (Pyodide)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress