Standard Library Tour
Python is often described as "batteries included". Every installation comes with the standard library, a large collection of modules for everyday jobs: counting things, random numbers, statistics, file operations, logging, compression and much more. You do not install anything; you just import them.
You have already met several of these modules in earlier lessons. This tour shows some new ones that save you real work, plus a map so you know where to look before writing code yourself or reaching for pip.
collections: smarter containers
The collections module adds container types that solve common problems in one line.
Counter counts how often each item appears. defaultdict is a dictionary that creates a default value for a missing key, so you never need to check whether a key exists first. deque (pronounced "deck") is a list-like queue that adds and removes items quickly at both ends, and can keep only the last few items with maxlen.
from collections import Counter, defaultdict, deque
votes = ["Meera", "Kabir", "Meera", "Isha", "Meera", "Kabir"]
tally = Counter(votes)
print(tally)
print("Class monitor:", tally.most_common(1)[0][0])
students = [("Aarav", "Rohtak"), ("Priya", "Jaipur"), ("Rohan", "Rohtak")]
by_city = defaultdict(list)
for name, city in students:
by_city[city].append(name)
print(dict(by_city))
recent = deque(maxlen=3)
for search in ["laptop bag", "earphones", "power bank", "phone cover"]:
recent.append(search)
print(list(recent))Counter({'Meera': 3, 'Kabir': 2, 'Isha': 1})
Class monitor: Meera
{'Rohtak': ['Aarav', 'Rohan'], 'Jaipur': ['Priya']}
['earphones', 'power bank', 'phone cover']With a normal dictionary, by_city[city].append(name) would raise KeyError the first time a city appears. defaultdict(list) creates an empty list automatically. The deque kept only the three most recent searches and dropped the oldest.
random, secrets and statistics
random makes pseudo-random choices for games, simulations and shuffling. Calling random.seed() with a fixed number makes the sequence repeat exactly, which is useful for testing.
import random
import statistics
random.seed(2026)
team = ["Aarav", "Priya", "Kabir", "Meera", "Rohan", "Isha"]
print(random.choice(team))
print(random.sample(team, 3))
print(random.randint(1, 6))
runs = [45, 12, 88, 67, 30, 101, 54]
print(round(statistics.mean(runs), 1), statistics.median(runs))
print(round(statistics.stdev(runs), 2))Aarav ['Kabir', 'Rohan', 'Aarav'] 2 56.7 54 31.37
statistics gives you the mean (average), median (middle value), standard deviation and more without any maths of your own.
import secrets
otp = f"{secrets.randbelow(10**6):06d}"
token = secrets.token_urlsafe(16)
print(len(otp), otp.isdigit())
print(len(token) > 16)6 True True
The actual OTP and token change on every run, so this example prints only checks about them. The :06d format pads the number with zeros so an OTP like 4,213 becomes 004213.
textwrap and hashlib
textwrap formats long text to a fixed width, which is handy for terminal output and receipts. hashlib computes a hash: a short fingerprint of some data. The same data always gives the same hash, and any change gives a completely different one, so hashes are used to check that a downloaded file was not damaged.
import hashlib
import textwrap
notice = ("The college library will remain closed on Saturday for stock "
"checking. Students must return all borrowed books by Friday evening.")
print(textwrap.fill(notice, width=40))
print(textwrap.shorten(notice, width=45, placeholder=" ..."))
data = "Fee receipt: Ananya, ₹12,500".encode("utf-8")
print(hashlib.sha256(data).hexdigest()[:16])
print(hashlib.sha256(data + b" ").hexdigest()[:16])The college library will remain closed on Saturday for stock checking. Students must return all borrowed books by Friday evening. The college library will remain closed on ... 89386cde500f5b83 e78a181167a4f3f5
Adding just one space changed the fingerprint completely. Note that a plain hash is not the right way to store passwords; real login systems use special slow password-hashing functions.
logging: better than print for programs
print() is fine while learning, but real programs use logging. Each message gets a level (DEBUG, INFO, WARNING, ERROR, CRITICAL), and you choose which levels to show, without deleting lines from your code. Messages can include the time and go to a file instead of the screen.
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
log = logging.getLogger("shop")
log.debug("Cart contents: %s", ["pen", "notebook"]) # hidden: below INFO
log.info("Order %d placed by %s", 1042, "Farhan")
log.warning("Only %d notebooks left", 3)
log.error("Payment gateway did not respond")INFO: Order 1042 placed by Farhan WARNING: Only 3 notebooks left ERROR: Payment gateway did not respond
The debug message is hidden because the level is set to INFO. Change it to logging.DEBUG while hunting a bug, and back again when you are done. Log messages go to the error stream (stderr) by default, which terminals show just like normal output.
A map of the standard library
Before you write something complicated or install a package, check whether a standard module already does it:
| Task | Module | Learn more |
|---|---|---|
| Paths, folders, reading files | pathlib | Reading & Writing Files |
| Copy, move, zip folders | shutil | shutil.copy(), shutil.make_archive() |
| JSON and CSV data | json, csv | JSON & CSV |
| Dates, times, time zones | datetime, zoneinfo | Dates & Times |
| Text patterns | re | Regular Expressions |
| Looping tools | itertools | Iterators & Generators |
| Caching, partial functions | functools | Decorators |
| Command-line options | argparse | Project: Expense Tracker |
| A small SQL database in a file | sqlite3 | sqlite3.connect("shop.db") |
| Fetching web pages | urllib.request | The requests package is friendlier |
| Running other programs | subprocess | subprocess.run(["git", "status"]) |
| Measuring speed | timeit | python -m timeit "sum(range(1000))" |
| Testing your code | unittest, doctest | Testing & Best Practices |
| Information about Python itself | sys, platform | sys.version, sys.argv |
The full list is in the official library reference. Skim it once; you will be surprised by how much is already there.
Common mistakes
- Writing your own version of a standard tool. Counting with a manual dictionary loop is fine for learning, but
Counteris shorter and clearer. - Using
randomfor security. Usesecretsfor OTPs, tokens and passwords. - Leaving debug
print()calls everywhere. Useloggingwith levels so you can turn messages on and off. - Naming your files after standard modules. A file called
logging.pyorstatistics.pyhides the real module; see Modules & Imports.
Key points
- The standard library ships with Python; import its modules without installing anything.
collectionsoffersCounter,defaultdictanddequefor counting, grouping and queues.randomis for games and simulations;secretsis for anything security-related.statistics,textwrapandhashlibhandle averages, text layout and data fingerprints.loggingreplaces debug prints with levelled messages you can switch on and off.- Python 3.14 adds
compression.zstd; check the library map before installing a package.
Exercise
A college quiz in Kochi collected answers to the question "Favourite programming language?" as one long string: "python java python c python javascript java python c". Use Counter to print the top two languages with their counts. Then use defaultdict(list) to group the words by their first letter, and print the result as a normal dictionary.
Show solution
from collections import Counter, defaultdict
answers = "python java python c python javascript java python c".split()
for language, count in Counter(answers).most_common(2):
print(language, count)
by_letter = defaultdict(list)
for word in sorted(set(answers)):
by_letter[word[0]].append(word)
print(dict(by_letter))python 4
java 2
{'c': ['c'], 'j': ['java', 'javascript'], 'p': ['python']}most_common(2) returns the two most frequent items as (item, count) pairs. Using set() removes repeated words before grouping, and sorted() keeps the output in a predictable order.
Quick Quiz
1. Which tool counts how many times each item appears in a list?
Counter builds a dictionary-like count of every item, with most_common() for the top ones.
2. Which module should you use to generate an OTP?
secrets produces unpredictable numbers suitable for security; random is predictable.
3. What does defaultdict(list) do when you access a missing key?
The factory, list, is called to make a default value for any new key.
4. Why use logging instead of print() in a real program?
Levels such as INFO and DEBUG let you control how much detail appears.
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
