Learn Python
Learn Python properly: the language itself, its data model and standard library, and how to write clear, tested, idiomatic Python that I would be happy for someone else to read.
This roadmap takes you from writing your first lines of code to mastering idiomatic, production-grade Python through hands-on project builds. Across ten phases and roughly three to five months at 8 hours per week, you will systematically explore language syntax, structural data models, standard library tools, testing frameworks, and advanced protocols. By the end, you will be able to design, structure, type-check, test, and package robust Python applications and libraries that fully leverage Python's unique data model.
By the end: You will be able to write idiomatic, type-annotated, and thoroughly tested Python libraries and tools, comfortably using the Python data model, decorators, generators, and standard packaging tools.
This is the map — make this roadmap yours
It shows what this journey generally looks like. Tell Kaidoro your version of the goal and it builds the plan around where you are actually starting, what to do first, the hours you really have, and what you have already finished.
Environment Setup and Core Language Mechanics
Establish a modern Python development environment and master foundational syntax, variables, primitive types, and control flow through small interactive tools.
- Set up modern Python and interactive tooling~3hLearn1 resource
A reliable local environment with interactive feedback is essential before writing application code.
You'll learn
- REPL — Read-Eval-Print Loop for rapid interactive code evaluation
- sys.version — built-in property exposing the active Python version
- terminal execution — running scripts using python script.py from the CLI
Install Python 3.12+, configure a code editor like VS Code or PyCharm, and learn how to run Python scripts both via command line and an interactive REPL like IPython. You will write a script that inspects your runtime environment and prints system details.
Done when: you can execute a script from your terminal that outputs the Python version, executable path, and current operating system platform.
How to work through it
- Install Python 3.12+ on your system
- Configure your text editor with Python language extensions
- Install IPython in a terminal for interactive experimentation
- Write a script importing sys and platform to print runtime information
- Build a CLI unit converter with conditional branches~4hBuild
Writing interactive scripts solidifies your understanding of type coercion and branching control flow.
You'll learn
- type casting — converting strings from standard input into numeric types
- f-strings — formatted string literals for clean text interpolation
- conditional logic — directing program execution flow based on boolean expressions
Build a command-line utility that prompts users for values and units (e.g., temperature, distance, weight) and computes conversions. Practice variables, primitive data types (integers, floats, strings, booleans), input parsing, and conditional branching (if/elif/else).
Done when: the converter handles at least three unit categories, performs valid mathematical conversions with formatted float output, and gracefully rejects invalid input options.
How to work through it
- Create a script handling user prompts via input()
- Convert string inputs to float types safely
- Implement branching logic with if, elif, and else blocks
- Format decimal output using f-strings
- Build a terminal-based number guessing game with loops~3hBuild
Loops and loop-control keywords are the core engine of iterative algorithmic logic in Python.
You'll learn
- random.randint — standard library function for pseudo-random integers
- while loop — iterative structure executing while a boolean condition remains true
- break and continue — statements to interrupt or advance loop iterations
Create an interactive guessing game where the computer selects a random number and gives directional hints (higher/lower) with a limited attempt counter. Implement while loops, for loops with ranges, loop control statements (break, continue, else-on-loop), and state tracking.
Done when: the game runs from start to finish, tracks attempts correctly, stops when guesses run out or the number is found, and reports round statistics.
How to work through it
- Import random and use randint to generate target values
- Implement a while loop to handle repeated guesses until termination
- Use break to exit early on victory and continue to bypass bad inputs
- Add an attempt tracking counter and victory/loss summary printouts
Core Data Structures and Comprehensions
Work deeply with Python's core collection types—lists, tuples, dictionaries, and sets—and master idiomatic idioms like comprehensions and structural unpacking.
- Implement an in-memory inventory tracker using collections~4hBuild1 resource
Dictionaries and lists form the foundational data storage layer for almost all Python data pipelines.
You'll learn
- list mutability — in-place modification of ordered sequences
- dictionary hashing — key-value mappings with O(1) lookup performance
- dict.get() — accessing dictionary values with safe default fallbacks
Build an inventory management CLI that stores item records using dictionaries nested inside lists. Practice indexing, slicing, inserting, updating, removing, and iterating over collection items using standard dictionary and list methods.
Done when: the script supports adding items, updating stock counts, deleting entries, and displaying formatted table summaries.
How to work through it
- Design the data structure using dictionaries for item entities and lists for collections
- Implement CRUD (create, read, update, delete) functions over the data structure
- Use dictionary methods like .get(), .keys(), and .items()
- Print formatted tabular data using string alignment methods
- Build a text analysis tool using sets and comprehensions~5hBuild
Comprehensions and set mathematics allow you to write concise, highly efficient, and idiomatic data transformations.
You'll learn
- list comprehension — compact syntax for generating new lists from iterables
- dict comprehension — expression-based construction of dictionaries
- set operations — union, intersection, and difference operations on unique collections
Build a script that parses raw text documents, computes word frequency distributions, identifies unique vocabulary across multiple files using set operations (unions, intersections, differences), and filters datasets using list and dict comprehensions.
Done when: the program accepts text files, computes word frequency counts, and outputs set comparisons between documents using list/dict comprehensions.
How to work through it
- Read raw text and normalize case and punctuation
- Generate unique token sets and perform set intersections and differences
- Build word count mappings using dictionary comprehensions
- Filter low-frequency words with nested list comprehensions
- Build a data restructuring pipeline using sequence unpacking~4hBuild
Idiomatic iteration patterns eliminate off-by-one errors and replace manual index arithmetic with clean expressions.
You'll learn
- extended iterable unpacking — extracting head, middle, and tail items with * syntax
- zip() — aggregating elements from multiple iterables into tuples
- enumerate() — yielding index and value pairs during iteration
Create a data transform script that processes raw nested tuples and lists from simulated legacy data. Apply tuple unpacking, extended unpacking (*rest), zip(), enumerate(), and sorted() with custom key functions to output clean structured records.
Done when: the script processes heterogeneous nested tuples and produces sorted, uniformly structured summaries without using manual index counters.
How to work through it
- Construct sample nested tuple data structures representing raw database rows
- Use tuple unpacking and starred expressions (*rest) to extract fields
- Iterate across parallel sequences using zip() and enumerate()
- Sort structured records with sorted() using lambda key functions
Modular Functions, Scopes, and Standard Libraries
Transition from scripts to modular software design by mastering function signatures, scope rules, module structures, and standard library tools.
- Build a flexible calculation engine using advanced function arguments~4hBuild
Clean API design in Python relies heavily on precise argument positioning and explicit keyword boundaries.
You'll learn
- positional-only parameters — arguments enforced before the / delimiter
- keyword-only parameters — arguments required by name after the * delimiter
- LEGB rule — Local, Enclosing, Global, Built-in variable resolution scopes
Write a multi-purpose calculation module that uses positional-only arguments, keyword-only arguments, default values, and arbitrary argument lists (*args, **kwargs). Enforce strict parameter signatures to prevent invalid usage.
Done when: the module exposes functions that strictly differentiate positional from keyword arguments, correctly handles arbitrary arguments, and includes full docstrings.
How to work through it
- Define functions with positional-only syntax (/) and keyword-only syntax (*)
- Implement variadic functions capturing *args and **kwargs
- Handle default parameter pitfalls (avoiding mutable defaults)
- Write comprehensive docstrings adhering to PEP 257 standards
- Refactor logic into a multi-file Python package~4hBuild1 resource
Understanding Python's import system and module resolution is essential for building scalable applications.
You'll learn
- __init__.py — file marking directory as an importable Python package
- __main__.py — entrypoint executed when a module is run with the -m flag
- sys.path — list of directories Python searches when resolving imports
Organize your converter, inventory, and calculation tools into a well-structured Python package containing multiple modules, proper
__init__.pyexports, and a central__main__.pyentrypoint. Run the package directly usingpython -m.Done when: you can execute the entire toolkit from the CLI using
python -m mytoolkitwith cleanly resolved relative and absolute imports.How to work through it
- Create a directory structure with package root, submodules, and __init__.py
- Configure relative imports within submodules
- Create a __main__.py file to make the package directory executable
- Verify execution via python -m without import errors
- Build a benchmark tool using itertools and collections modules~5hBuild
The standard library collections and itertools provide highly optimized C-level abstractions for common data manipulation tasks.
You'll learn
- collections.defaultdict — dictionary subclass calling a factory function for missing keys
- collections.Counter — dict subclass designed specifically for counting hashable objects
- itertools.groupby — iterator generating consecutive keys and groups from an iterable
Build a statistical analysis script that processes sequences using standard library modules including collections (defaultdict, Counter, deque, namedtuple) and itertools (chain, cycle, groupby, islice). Benchmark the performance against pure list implementations.
Done when: the tool runs data aggregation benchmarks using both pure lists and specialized collections, printing execution time comparisons and memory summaries.
How to work through it
- Implement frequency counters with collections.Counter and groupings with defaultdict
- Create sliding windows and combined streams using itertools
- Use time.perf_counter() to measure runtime performance
- Present comparative timing metrics in a formatted terminal table
Object-Oriented Programming and the Python Data Model
Learn object-oriented design in Python by implementing classes, inheritance, encapsulation, dataclasses, and core dunder (special) methods.
- Build a banking domain model with encapsulation and properties~5hBuild
Pythonic OOP avoids unnecessary getters and setters in favor of clean properties and explicit dunder methods.
You'll learn
- @property — decorator enabling getter, setter, and deleter methods with attribute syntax
- __repr__ vs __str__ — developer representation vs user-facing string formatting
- @classmethod — method receiving the class object (cls) rather than instance (self)
Model a banking domain with classes for accounts, transactions, and customers. Implement state encapsulation with private attributes, dynamic properties (@property and setter), custom string representations (repr and str), and class methods.
Done when: the domain model prevents negative balances via property setters, maintains valid transaction ledgers, and prints descriptive debug representations via repr.
How to work through it
- Define Account and Transaction classes with __init__ initialization
- Implement @property and @balance.setter with validation logic
- Define __str__ for user-friendly printing and __repr__ for unambiguous debugging
- Add @classmethod factory constructors for creating accounts from raw data
- Implement a custom Vector class supporting arithmetic protocols~5hBuild1 resource
Implementing arithmetic protocols makes your custom types behave like first-class native Python objects.
You'll learn
- operator overloading — defining operator behavior on custom objects using dunder methods
- __rmul__ — right-hand (reflected) multiplication protocol method
- NotImplemented — singleton returned when a type does not support an operation with another
Create a 2D/3D Vector mathematical class that implements arithmetic and comparison dunder methods. Support addition (+), subtraction (-), scalar multiplication (*), equality (==), and truth-value testing (bool).
Done when: your custom Vector class allows intuitive mathematical expressions (v3 = v1 + v2 * 3), checks equality accurately, and handles type mismatch errors gracefully.
How to work through it
- Implement __add__, __sub__, and __mul__ with type checking
- Add __rmul__ to support reverse scalar multiplication (e.g., 3 * v)
- Implement __eq__ and __abs__ for magnitude calculations
- Implement __bool__ to evaluate vector magnitude against zero
- Build a card deck simulator implementing the Sequence protocol~4hBuild
Python relies on duck typing and protocols: satisfying minimal dunder methods gives full access to language features without explicit inheritance.
You'll learn
- Sequence protocol — emulating read-only sequences with __len__ and __getitem__
- dataclasses.dataclass — decorator generating boilerplate __init__ and comparison methods
- duck typing — polymorphism based on object capabilities rather than class hierarchy
Implement a custom Deck class that implements
__len__and__getitem__. Demonstrate how implementing these two methods automatically gives your object iteration, slicing, containment checks (in), and compatibility with random.choice.Done when: the Deck instance supports slicing (deck[0:5]), reverse iteration (reversed(deck)), random picking via random.choice, and sorting using dataclass card representations.
How to work through it
- Define a Card dataclass using @dataclass with rank and suit
- Create a Deck class implementing __len__ and __getitem__
- Test slicing, indexing, and iteration on the deck instance
- Pass the deck to standard functions like random.choice() and sorted()
File Operations, Serialization, and Context Managers
Work with local file systems using modern pathlib, parse common structured data formats (JSON, CSV), and build custom context managers using the `with` statement.
- Build a file organizer utility using pathlib~4hBuild1 resource
Modern pathlib provides an intuitive object-oriented interface for cross-platform filesystem operations.
You'll learn
- pathlib.Path — object-oriented representation of filesystem paths
- Path.rglob — recursive pattern matching over directory structures
- cross-platform compatibility — handling path separators consistently across OS platforms
Create a command-line utility that inspects a target directory, categorizes files by extension and modification dates, creates sorted subfolders, and moves items safely. Use pathlib.Path exclusively instead of legacy os.path methods.
Done when: the script cleanly inspects nested directories using pathlib globbing, handles filename collisions, and organizes files into categorized subdirectories.
How to work through it
- Use Path.cwd() and Path.glob() / rglob() to discover files
- Extract file stems, suffixes, and metadata via Path methods
- Safely construct new directory trees using Path.mkdir(parents=True, exist_ok=True)
- Move files with Path.rename() or shutil
- Build a JSON and CSV data migration tool~4hBuild
Real-world Python applications constantly serialize and deserialize structured data between formats.
You'll learn
- json.loads / json.dumps — serializing and deserializing JSON strings
- csv.DictReader / csv.DictWriter — mapping rows to dictionaries for tabular data
- encoding parameters — specifying explicit UTF-8 encoding in open()
Build a data migration script that reads complex nested JSON configuration files, validates the schema, transforms fields, and writes normalized tabular records into CSV files using csv.DictWriter, and vice versa using csv.DictReader.
Done when: the migration tool converts nested JSON payloads to normalized CSV spreadsheets and reconstructs the JSON structure back without data loss.
How to work through it
- Read and parse JSON files using json.load() with custom deserializers
- Flatten nested dictionaries into flat records for tabular storage
- Write records using csv.DictWriter with specified fieldnames
- Implement reverse transformation using csv.DictReader and json.dump()
- Create custom context managers for resource handling~5hBuild
Context managers guarantee deterministic resource acquisition and cleanup, preventing resource leaks.
You'll learn
- __enter__ and __exit__ — dunder methods defining context management lifecycle
- contextlib.contextmanager — decorator converting generator functions into context managers
- atomic operations — patterns ensuring file modifications succeed completely or not at all
Create custom context managers using both the class-based protocol (
__enter__and__exit__) and the generator-basedcontextlib.contextmanagerdecorator. Build managers for timing code blocks, temporarily redirecting standard output, and handling atomic file writes.Done when: your atomic file writer context manager ensures that files are only modified if the inner block finishes without raising an exception.
How to work through it
- Build a class-based Timer context manager implementing __enter__ and __exit__
- Handle exception propagation and suppression logic within __exit__
- Implement an AtomicFileWriter using contextlib.contextmanager and temporary files
- Verify that errors during writes leave original target files untouched
Error Handling, Logging, and Testing with Pytest
Master robust defensive programming by creating custom exception hierarchies, setting up structured logging, and writing automated test suites with pytest.
- Build a custom exception hierarchy with structured logging~4hBuild1 resource
Production Python applications require structured log streams and explicit error types rather than raw prints and blanket try/except blocks.
You'll learn
- exception chaining — preserving original traceback using the 'raise ... from err' syntax
- logging handlers — routing log records to console, files, or rotating storage
- custom exceptions — application-specific exception types for distinct error domains
Refactor an existing file parsing project to replace generic print statements with structured logging using the
loggingmodule. Design a domain-specific hierarchy of custom Exception classes that capture structured error details.Done when: all application events are output through configured loggers (with levels, timestamps, and formatting) and invalid states trigger custom exceptions caught cleanly by top-level handlers.
How to work through it
- Define custom exception classes inheriting from Exception
- Configure logging with logging.basicConfig, formatters, and RotatingFileHandler
- Use logger.info, logger.warning, and logger.exception with stack traces
- Catch specific custom exceptions and preserve error context with 'from err'
- Write comprehensive unit tests with pytest fixtures and parametrization~5hBuild1 resource
Pytest is the standard testing tool in the Python ecosystem due to its clean syntax and powerful fixture architecture.
You'll learn
- pytest fixtures — dependency injection mechanism for test resources
- pytest.mark.parametrize — running a single test function across multiple input matrices
- assert introspection — automatic detailed failure reports on assertion failure
Install pytest and write a thorough automated test suite for your domain models and parser tools. Utilize pytest fixtures for test setup/teardown and
@pytest.mark.parametrizeto run tests over dozens of input/expected-output combinations.Done when: the test suite executes with 100% pass rate, contains parametrized test cases, and runs fixtures with clean teardowns.
How to work through it
- Install pytest and configure pytest.ini / pyproject.toml
- Write unit tests using simple assert statements
- Create reusable test data fixtures with @pytest.fixture and yield teardown
- Parametrize edge-case test matrices using @pytest.mark.parametrize
- Mock external dependencies and measure test coverage~4hBuild
Mocking isolates unit tests from external instability, ensuring fast and deterministic test runs.
You'll learn
- tmp_path — built-in pytest fixture providing unique temporary directory Path objects
- unittest.mock.patch — replacing target objects with Mock instances during tests
- branch coverage — verifying all execution branches in conditional logic are tested
Extend your test suite to test code interacting with files and network calls without touching real external resources. Use
unittest.mock.patchand pytest'smonkeypatch/tmp_pathfixtures, then measure test coverage usingpytest-cov.Done when: the test suite achieves over 90% branch coverage reported via pytest-cov with zero network or real filesystem dependencies.
How to work through it
- Use tmp_path fixture to test filesystem interactions in isolated sandbox directories
- Mock external function calls using unittest.mock.patch and MagicMock
- Assert mock call counts and received arguments
- Generate an HTML coverage report using pytest --cov
Advanced Idioms: Generators, Iterators, and Decorators
Deepen your Python mastery by writing custom iterators, memory-efficient generator pipelines, and reusable function and class decorators.
- Build a streaming log processor with generator pipelines~4hBuild
Generators enable lazy evaluation, allowing Python programs to process massive data streams without loading them into RAM.
You'll learn
- yield keyword — pausing function execution and producing a value to the caller
- generator pipeline — composing multiple generator functions in series
- lazy evaluation — delaying expression evaluation until value is requested
Create a log analysis tool capable of processing multi-gigabyte log files with near-zero memory consumption. Chain generator functions using
yieldstatements to filter, map, parse, and aggregate lines sequentially.Done when: the streaming pipeline parses and filters large files in constant O(1) memory space, verified by memory profiling.
How to work through it
- Write generator functions yielding parsed lines with yield statements
- Chain generator filters into a processing pipeline
- Use generator expressions for inline data transformations
- Track memory usage before and after using sys.getsizeof or tracemalloc
- Implement custom function decorators with functools.wraps~5hBuild
Decorators are Python's primary metaprogramming tool for cleanly injecting cross-cutting concerns.
You'll learn
- decorator pattern — higher-order function modifying the behavior of wrapped functions
- functools.wraps — preserving original function name, docstrings, and signature
- decorator factory — outer function returning a decorator parameterized by arguments
Build a collection of utility decorators:
@timerfor execution timing,@retry(times=3)with configurable arguments,@rate_limit, and@cache_lrumemoization. Preserve function metadata usingfunctools.wraps.Done when: the decorators can wrap arbitrary functions with varying signatures, handle arguments correctly, and preserve the original function's
__name__and docstrings.How to work through it
- Write a simple decorator wrapping functions with inner wrapper functions
- Apply functools.wraps to maintain introspection metadata
- Create decorator factories that accept configuration parameters (e.g., retry count)
- Test decorators against both positional and keyword argument functions
- Build a class-level validation decorator and descriptor~5hBuild
Descriptors power Python's internal mechanics for properties, methods, and ORMs.
You'll learn
- descriptor protocol — objects defining __get__, __set__, or __delete__ methods
- __set_name__ — hook automatically assigning descriptor instance attribute names
- class decorator — function receiving a class and returning a modified class
Implement custom descriptor classes that enforce type and range validation on class attributes (e.g., IntegerField, StringField). Compare descriptor behavior with property decorators and write a class decorator that auto-applies descriptors.
Done when: any invalid attribute assignment on decorated classes immediately raises a descriptive ValidationError managed by your custom descriptors.
How to work through it
- Implement __get__, __set__, and __set_name__ in a Validator descriptor class
- Integrate descriptors into a sample entity model
- Create a class decorator that inspects class attributes and binds descriptors
- Write unit tests verifying validation rejection on bad assignment
Type Hinting and Static Analysis
Adopt modern Python static typing by annotating codebases with typing constructs, Generics, Protocols, and enforcing strict checks using Mypy.
- Add static type annotations to an existing codebase~4hBuild1 resource
Type hints make code self-documenting, catch subtle bugs before runtime, and enhance IDE autocompletion.
You'll learn
- type hints — annotations declaring expected types for variables and functions
- mypy — static type checker analyzing Python code without executing it
- Union and Optional — typing constructs allowing multiple types or None values
Annotate functions and classes using primitive types, collections (
list[str],dict[str, int]),Optional,Union(and the|union syntax), and callable signatures. Configure Mypy and resolve initial type errors.Done when: Mypy passes on the annotated codebase under standard configuration with zero type errors reported.
How to work through it
- Install mypy and configure a mypy.ini / pyproject.toml configuration file
- Annotate function parameter types and return types across modules
- Use modern union syntax (int | str) and Optional types
- Run mypy . and resolve detected type mismatches
- Implement Generics and structural subtyping with typing.Protocol~5hBuild
Protocols provide static duck typing, allowing compile-time type verification without rigid class inheritance hierarchies.
You'll learn
- typing.Protocol — static duck typing mechanism defining required interface methods
- TypeVar — variable standing in for an unknown type in generic functions and classes
- mypy --strict — strictest static type validation mode enforcing exhaustive annotations
Design generic data structures using
TypeVar/Generic(e.g., a custom Stack or Repository) and decouple components by defining structural interfaces usingtyping.Protocolinstead of concrete base classes.Done when: Mypy verifies type safety across generic classes and confirms that duck-typed objects satisfy declared Protocol definitions under
--strictmode.How to work through it
- Define generic classes using TypeVar and Generic (or PEP 695 type parameters)
- Define a Serializable or Renderable Protocol using typing.Protocol
- Create independent classes satisfying the protocol without subclassing it
- Verify complete type conformance with mypy --strict
Concurrency: Threads, Processes, and Asyncio
Understand Python's concurrency landscape, the Global Interpreter Lock (GIL), and when to use multithreading, multiprocessing, or asynchronous I/O.
- Build a concurrent web scraper using ThreadPoolExecutor and ProcessPoolExecutor~5hBuild
Choosing between threads and processes requires understanding whether your bottlenecks are I/O bound or CPU bound in the presence of the GIL.
You'll learn
- GIL (Global Interpreter Lock) — mutex preventing multiple native threads from executing Python bytecode simultaneously
- ThreadPoolExecutor — managing pools of worker threads for I/O concurrency
- ProcessPoolExecutor — bypassing the GIL by spawning distinct Python OS processes
Create a script that compares concurrent execution models. Fetch multiple web endpoints concurrently using
concurrent.futures.ThreadPoolExecutor(I/O bound), then perform CPU-intensive hashing calculations across multiple cores usingProcessPoolExecutor.Done when: the script benchmarks serial vs multi-threaded I/O fetching and serial vs multi-process CPU processing, demonstrating expected speedups.
How to work through it
- Implement sequential download and processing baselines
- Wrap I/O operations inside ThreadPoolExecutor and map tasks
- Wrap CPU-bound hashing calculations inside ProcessPoolExecutor
- Measure and explain the performance differences and CPU core utilization
- Build an asynchronous rate-limited API client with asyncio and httpx~5hBuild1 resource
Asyncio provides high-throughput cooperative multitasking for modern network services.
You'll learn
- async / await — syntax for writing non-blocking asynchronous coroutines
- event loop — central execution mechanism scheduling and running asynchronous tasks
- asyncio.Semaphore — concurrency synchronization primitive limiting concurrent coroutines
Build an asynchronous client that queries a REST API for hundreds of resources. Use
asyncio,async/await,asyncio.Semaphorefor concurrency rate limiting, andasyncio.gatherfor coordinating parallel tasks.Done when: the client executes 100+ asynchronous requests within strict concurrency limits (e.g., max 5 concurrent requests) and handles timeouts and failures gracefully.
How to work through it
- Write asynchronous functions using async def and await syntax
- Execute concurrent coroutines using asyncio.gather()
- Limit simultaneous outbound connections using asyncio.Semaphore
- Implement graceful exception handling and timeout cancellations using asyncio.wait_for
Packaging, Tooling, and Capstone Project
Synthesize all skills by building, styling, typing, testing, and packaging an idiomatic, production-grade CLI application configured with modern pyproject.toml standards.
- Configure modern project tooling with Ruff and pyproject.toml~3hBuild
Standardized configuration in pyproject.toml and automated formatters guarantee that your code adheres to community standards (PEP 8) effortlessly.
You'll learn
- pyproject.toml — unified configuration file for Python build tools and linters
- ruff — extremely fast Python linter and code formatter written in Rust
- PEP 8 — official style guide for Python code
Initialize a clean project layout according to PEP 621 / PEP 518 standards using
pyproject.toml. Configurerufffor ultra-fast linting and code formatting, configure Mypy with strict settings, and set up Git pre-commit hooks.Done when: running a single command runs formatting, linting, and type checking across your codebase with zero warnings.
How to work through it
- Create a pyproject.toml with project metadata and dependencies
- Configure ruff for code style linting and formatting rules
- Set up strict type checking rules in pyproject.toml
- Verify automated checking runs cleanly across the repository
- Build the capstone project: an idiomatic CLI data processing tool~8hBuild
Integrating all language features into a coherent project proves your ability to build complete, maintainable Python applications.
You'll learn
- argparse — standard library module for writing user-friendly CLI interfaces
- domain-driven structure — organizing code by business concepts rather than technical layers
- error boundaries — isolating subsystem failures from crashing the main CLI loop
Design and build a complete CLI tool (such as an automated markdown link validator and static asset analyzer). It must feature clean modular architecture, custom data structures implementing dunder protocols, async fetching, custom exceptions, robust logging, and full type annotations.
Done when: the CLI tool runs smoothly from terminal commands with flags, parses local and remote inputs asynchronously, logs cleanly, and handles all runtime failures gracefully.
How to work through it
- Design the application architecture using clean domain models and protocols
- Build the CLI interface using argparse or click
- Integrate async network fetching with semaphore concurrency control
- Add detailed logging and domain-specific error handling
- Complete test suite, documentation, and package distribution build~6hReview1 resource
A Python project is complete when it is tested, documented, and reliably installable by others.
You'll learn
- wheel (.whl) — standard built-package format for distributing Python software
- python -m build — standard tool for building PEP 517 packages
- virtual environments (venv) — isolated directory trees for managing dependencies
Write a complete pytest suite covering the capstone application with fixtures, mocks, and parametrization (>90% coverage). Add comprehensive docstrings and build an installable
.whldistribution package using thebuildtool.Done when: the test suite passes with 90%+ coverage, Mypy passes in strict mode, and you can install your package into a clean virtual environment using
pip install dist/*.whland run the CLI command successfully.How to work through it
- Write comprehensive pytest test cases for all modules with mocking
- Verify >90% code coverage and strict Mypy conformance
- Build source distributions and wheels using python -m build
- Test installation of the wheel in an isolated clean virtual environment
How the plan fits together
10 phases in 9 stages. Anything on the same row can be worked on at the same time.
An arrow points from a phase to the work it unlocks: before starting any phase, every phase with an arrow into it has to be finished first.
- Solid arrow
- Must be finished before the phase it points to
- Dashed arrow
- Same rule, but the prerequisite sits more than one stage back
Resources
14 in this plan's library, beyond the links on individual tasks.
Core Documentation and Books
Primary references, official documentation, and deep dives.
- Fluent Python (2nd Edition)
Use for an in-depth dive into idiomatic Python, covering data models, protocols, type hints, and modern concurrency.
oreilly.com · O'Reilly Media · Book · $60–$80
- Mypy Documentation
Use to configure static analysis, strict verification flags, and gradual typing across your codebases.
mypy.readthedocs.io · Mypy core development team · Documentation · Free
- PEP 8 – Style Guide for Python Code
Use as the foundational standard for consistent code formatting and naming conventions across the Python ecosystem.
peps.python.org · Python Software Foundation · Style Guide · Free
- pytest Documentation
Use to master idiomatic Python testing conventions, fixture dependency injection, and test parametrization.
docs.pytest.org · pytest development team · Documentation · Free
- Python 3 Module of the Week (PyMOTW-3)
Consult this library tour to see clear, practical code examples for standard library modules like itertools, collections, and functools.
pymotw.com · Doug Hellmann · Reference Guide · Free · Intermediate
- Python Distilled
Use to understand Python runtime mechanics, function call frames, generators, and I/O abstractions without outdated patterns.
pearson.com · Addison-Wesley Professional · Book · $30–$40
- Python Packaging User Guide (PyPUG)
Use to learn modern package structuring, pyproject.toml configuration, distribution building, and publishing.
packaging.python.org · Python Packaging Authority (PyPA) · Documentation · Free
- Python Testing with pytest, Second Edition
A structured guide to mastering test parameterization, custom fixtures, mocking, and organizing test suites.
pragprog.com · The Pragmatic Bookshelf · Book · ~$32 for ebook · Intermediate
- Ruff Documentation
Use to set up high-performance linting, automatic import sorting, and code formatting enforcing PEP 8.
docs.astral.sh · Astral Software · Documentation · Free
- The Python Data Model Reference
Use to learn dunder methods and master how user-defined classes integrate directly with core Python syntax.
docs.python.org · Python Software Foundation · Documentation · Free
- The Python Discourse Forum (discuss.python.org)
Use to participate in core language discussions, packaging standard evolutions, and PEP feedback with maintainers.
discuss.python.org · Python Software Foundation · Community Forum · Free
- The Python Tutorial
Use as the authoritative introductory reference for core control flow, built-in sequences, mapping types, and standard library conventions.
docs.python.org · Python Software Foundation · Documentation · Free
- The Python typing Standard Library Documentation
Use to implement static type hints, generic types, parameter specs, and structural subtyping protocols.
Python Software Foundation · Documentation · Free
Community and Standards
Python enhancement proposals (PEPs) and community forums.
- PEP 484 – Type Hints
Read this PEP to understand the design philosophy, constraints, and intentions behind static type annotations in Python.
peps.python.org · Python Software Foundation · Specification · Free · Intermediate