# How I write Python ## Contents ## Library recommendations {#lib-recs} ### HTTP client {#http} [HTTPX](https://www.python-httpx.org/) offers a similar API to [Requests](https://docs.python-requests.org/) in both sync and async and with integrated type annotations. (There are third-party type annotations for Requests.) HTTPX makes it easy to use a SOCKS proxy. [`urllib.request`](https://docs.python.org/3/library/urllib.request.html) in the standard library works well as a fallback. ### DOM [Selectolax](https://github.com/rushter/selectolax) is faster than [Beautiful Soup](https://beautiful-soup-4.readthedocs.io/) with either [html5-parser](https://html5-parser.readthedocs.io/) or [html5lib](https://github.com/html5lib/html5lib-python). It is easier to install than html5-parser since it doesn't require disabling binary wheels for [lxml](https://lxml.de/). The API design helps with type safety. ### Configuration {#config} [tomllib](https://docs.python.org/3/library/tomllib.html) has been part of the standard library since Python 3.11. While [`configparser`](https://docs.python.org/3/library/configparser.html) is also in the standard library, [TOML](https://toml.io) is standardized and allows more structure. For writing TOML files, there is [tomli-w](https://github.com/hukkin/tomli-w). ### Date and time {#date-time} [Whenever](https://whenever.readthedocs.io/) correctly handles daylight saving time and uses types to prevent common mistakes. For more context, see ["Ten Python datetime pitfalls, and what libraries are (not) doing about it"](https://dev.arie.bovenberg.net/blog/python-datetime-pitfalls/) by Arie Bovenberg (2024). ### Markdown rendering {#markdown} [markdown-it-py](https://github.com/executablebooks/markdown-it-py) follows the [CommonMark](https://commonmark.org/) standard, is typed, and is [faster](https://markdown-it-py.readthedocs.io/en/latest/performance.html) than other CommonMark libraries implemented in pure Python. ### Serialization {#serialization} [msgspec](https://jcristharif.com/msgspec/) provides fast JSON, MessagePack, TOML, and YAML serialization of [dataclass](https://docs.python.org/3/library/dataclasses.html)-like classes with type support. ### Templating {#template} [Jinja](https://jinja.palletsprojects.com/) offers expressive, flexible templates for HTML and other text formats. Its [macros](https://jinja.palletsprojects.com/en/stable/templates/#macros) have proven particularly useful in practice. ### URLs {#url} [yarl](https://yarl.aio-libs.org/en/latest/) percent-decodes paths and has a well-designed API with properly named fields and query parameters stored in a `MultiDict`. As a fallback, [`urllib.parse`](https://docs.python.org/3/library/urllib.parse.html) in the standard library can handle both parsing and quoting. ### XML [xmltodict](https://github.com/martinblech/xmltodict) is the most fun XML library I've used. Despite its name, xmltodict is bidirectional: it can both parse and generate XML. ## Development tooling {#dev-tool} I have a [Copier template](https://github.com/dbohdan/python-template) that packages my preferred development tooling. [Type checkers](#type-checkers) are covered in the static-typing section. ### Project management {#pm} [uv](https://github.com/astral-sh/uv) is fast and manages Python versions as well as projects. It can also run single-file [scripts with dependencies](/scripts-with-dependencies). As a fallback, [Poetry](https://github.com/python-poetry/poetry) is capable and uses standard metadata since version 2. Poetry works on platforms where uv doesn't, like NetBSD, though it has [problems with PyTorch](https://github.com/python-poetry/poetry/issues/6409). ### Linting and formatting {#lint-format} [codespell](https://github.com/codespell-project/codespell) checks for common misspellings in code. [Ruff](https://docs.astral.sh/ruff/) is a fast Python linter and code formatter written in Rust that can replace many other tools, like `black`, `isort`, `pylint`, and `flake8`. ### Distribution {#distrib} [shiv](https://github.com/linkedin/shiv) is a command line utility for building self-contained Python [zipapps](https://docs.python.org/3/library/zipapp.html). Its only serious downside is that it only packages binary dependencies [for the current platform](https://github.com/linkedin/shiv/issues/26). ### Testing {#test} [pytest](https://docs.pytest.org/) produces more readable tests with `assert` compared to the specialized assertions in [`unittest`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaisesRegex). It has a coverage plugin, [pytest-cov](https://pytest-cov.readthedocs.io/). As a fallback, `unittest` in the standard library isn't bad. ## Static typing {#typing} Python has robust optional static typing. If you took a break from Python in the mid-2010s like I did, it may come as a surprise. This page links to resources for writing statically-typed Python, plus a few that make use of type hints at runtime. ### Articles {#typing-articles} - ["Deploying a distributed system? A type system helps a lot"](http://catern.com/progsys.html), Spencer Baugh (2021). - ["Algebraic Data Types in (typed) Python"](https://threeofwands.com/algebraic-data-types-in-python/), Tin Tvrtković (2023) - ["Writing Python like it's Rust"](https://kobzol.github.io/rust/python/2023/05/20/writing-python-like-its-rust.html), Jakub Beránek (2023). The author's style resembles the style I have arrived it. - ["Shape typing in Python"](https://jameshfisher.com/2024/04/12/shape-typing-in-python/), Jim Fisher (2024) ### Exercises {#typing-exercises} - [Python Type Challenges](https://github.com/laike9m/Python-Type-Challenges) ### Official documentation {#typing-official-docs} - ["Static Typing with Python"](https://typing.readthedocs.io/en/latest/) - ["`typing` --- Support for type hints"](https://docs.python.org/3/library/typing.html) ### Packages {#typing-packages} #### CLI {#typing-cli} - [jsonargparse](https://github.com/omni-us/jsonargparse)---"Implement minimal boilerplate CLIs derived from type hints and parse from command line, config files and environment variables" - [Typed Argument Parser (Tap)](https://github.com/swansonk14/typed-argument-parser)---"Typed argument parser for Python" - [Typer](https://github.com/tiangolo/typer)---"Typer, build great CLIs. Easy to code. Based on Python type hints." - [tyro](https://github.com/brentyi/tyro)---"Zero-effort CLI interfaces & config objects, from types" #### Error handling {#typing-errors} - [poltergeist](https://github.com/alexandermalyga/poltergeist)---"Rust-like error handling in Python, with type-safety in mind." ### Type checkers {#type-checkers} My preferred type checker is [Pyright](https://github.com/microsoft/pyright). - Fast - Good error messages - [Python type checkers](https://github.com/stars/dbohdan/lists/python-type-checkers)---my GitHub list ### See also {#typing-see-also} - ["Awesome Python Typing"](https://github.com/typeddjango/awesome-python-typing)---a collection of links to software and articles ## Page metadata URL: Published 2024-06-15, updated 2025-12-28. Tags: - bookmarks - programming - programming languages - Python