asyncio all the things with Omnilib
On this episode, you'll meet John Reese. John is the creator of Omnilib, which includes packages such as aioitertools, aiomultiprocess, and aiosqlite. Join us as we async all the things.
Episode Deep Dive
Guest Introduction and Background
John Reese is a seasoned Python developer deeply involved in the Python community and interested in advanced performance techniques using asyncio
. Professionally, he works at Facebook (Meta) on Python foundations and tooling. John is the creator of OmniLib, which houses Python libraries aimed at simplifying asynchronous workflows. These libraries include AIO SQLite
, AIO Itertools
, AIO Multiprocess
, and AQL
, each one designed to let developers “async all the things.”
What to Know If You're New to Python
Below are a few helpful points if you're just getting started with Python or asynchronous programming so you can follow along with this episode more easily:
- Understanding that Python’s
asyncio
is a way to do concurrency without relying on multi-threading is key. - Knowing the difference between CPU-bound and I/O-bound tasks will help you decide which async or parallel approach is best.
- Recognizing that Python code runs under the global interpreter lock (GIL) clarifies why libraries like
multiprocessing
or distributed async tools can unlock true parallelism.
Key Points and Takeaways
- OmniLib’s Async Building Blocks
John Reese created OmniLib as an umbrella organization for several high-quality Python libraries focused on asynchronous workflows. It features a consistent coding style, strong documentation, and a welcoming code-of-conduct. The libraries under OmniLib address common async patterns such as database interaction, concurrency with multiple processes, and iterables. Their goal is to make async capabilities more straightforward, even for large-scale applications.
- Links and Tools:
- AIO Multiprocess: Combining AsyncIO with Multiple Processes
This library allows you to run Python code across multiple processes (one per CPU core), each hosting an event loop, giving you both concurrency and true parallelism. It’s especially valuable for high-scale tasks such as web scraping or network I/O to many servers. Because each process can handle multiple async tasks, you avoid the overhead of creating an enormous number of single-purpose processes.
- Links and Tools:
- Dealing with the Global Interpreter Lock (GIL)
Python’s GIL ensures only one thread modifies Python objects at a time, which simplifies development but can limit CPU-bound multithreading performance. John highlighted how async and multiprocessing can work around the GIL, especially when you are waiting on I/O or distributing CPU-intensive workloads across processes.
- Links and Tools:
- Guide to concurrency in Python (general reference)
- Links and Tools:
- AIO Itertools for Async Iteration
Modeled after Python’s built-in
itertools
, this library handles async generators and iterables. It includes functions such as concurrency-limitedgather
to prevent overloading the event loop with thousands of tasks. Its chaining and batching features help handle streaming data efficiently, making it straightforward to build pipelines of async transformations.- Links and Tools:
- AIO SQLite for Asynchronous Database Access
SQLite is a light but powerful database engine included with Python.
AIO SQLite
wraps standard SQLite calls in a background thread, exposing them via async/await. While SQLite isn’t inherently multi-thread-friendly, this library cleverly coordinates access so your async code never blocks while queries run on a separate thread.- Links and Tools:
- AQL: A DSL for ORM-like SQL
AQL aims to unify a typed approach to generating SQL queries, letting you write queries with method calls (e.g.,
table.select().where(...)
). It can produce backend-specific SQL for different database engines. Although still evolving, its consistent interface across multiple databases is a big step in bridging ORM convenience and raw SQL performance.- Links and Tools:
- Benefits and Pitfalls of AsyncIO
AsyncIO is perfect for scaling I/O-bound tasks, such as network operations, web scraping, or reading many files concurrently. However, you can run into complexity if you try to adapt existing synchronous code by sprinkling in
async
without proper design. Understandingasync with
,async for
, and how to manage an event loop is crucial for success.- Links and Tools:
- Combining Async and Distributed Systems If you need to go beyond your local machine’s limits, you can embed async code in distributed frameworks. AIO Multiprocess is just one example of parallelizing on a single system; you can also extend concurrency to clusters using more advanced tooling. The concept remains: quickly release control while waiting for I/O, enabling massive throughput.
- Adopting Open Source and Inclusivity John founded OmniLib with a welcoming code-of-conduct to encourage diverse contributors. He emphasizes that an inclusive environment helps open-source projects thrive. If you’re adopting any OmniLib library, you can contribute not just code but also ideas and reviews, even if you’re new to open source.
- Bowler and USort: Tools for Code Modernization Outside OmniLib, John has built tools like Bowler for code refactoring and USort for deterministic import sorting. These emerged from scaling Python within large organizations, ensuring code quality and consistency. They’re good examples of Python’s ecosystem supporting incremental improvement.
- Links and Tools:
Interesting Quotes and Stories
From TI-99 to Ansible “Hello World”: John recalled his earliest programming memory on a TI-99-4A, showing how simple personal projects eventually led to building open-source libraries used at scale.
On Overthreading: One memorable story highlighted the trap of thinking “more threads solves everything,” only to discover that thousands of threads can slow an application. Instead, concurrency-limited gather in
asyncio
or using processes more wisely can be far more efficient.
Key Definitions and Terms
- GIL (Global Interpreter Lock): A lock in CPython ensuring only one thread runs Python code at a time, simplifying memory management but limiting multithreading performance.
- AsyncIO: A Python framework for asynchronous programming that uses an event loop and cooperative multitasking (via
async
/await
), well suited for I/O-bound operations. - Event Loop: The engine that schedules and runs
async
tasks. It continuously checks if any tasks are ready to proceed. - AIO: Often a shorthand prefix meaning “Asynchronous I/O.”
- Multiprocessing: The technique of running code across multiple CPU cores or processes to bypass the GIL for CPU-intensive work.
Learning Resources
Here are a few curated courses and references that dive deeper into Python and async topics:
- Python for Absolute Beginners: Perfect for anyone brand new to coding in Python.
- Async Techniques and Examples in Python: Understand how to use
asyncio
, threads, multiprocessing, and more for parallelism in Python. - Modern APIs with FastAPI and Python: If async web frameworks interest you, check out FastAPI’s powerful async features.
Overall Takeaway
This episode highlights how to push Python’s concurrency and parallelism to the next level by blending asyncio
with carefully managed processes. John’s OmniLib suite provides practical frameworks for async iteration, database access, and bridging the gap between CPU-intensive and I/O-heavy workloads. Whether you’re scaling to hundreds of network calls or wanting a more elegant approach to concurrency, OmniLib demonstrates that Python can “async all the things” with performance and clean design in mind.
Links from the show
awesome-asyncio: github.com
unsync: asherman.io
Live Youtube Stream: youtube.com
Charities
Power On: poweronlgbt.org
The Trevor Project: thetrevorproject.org
Episode transcripts: talkpython.fm
--- Stay in touch with us ---
Subscribe to Talk Python on YouTube: youtube.com
Talk Python on Bluesky: @talkpython.fm at bsky.app
Talk Python on Mastodon: talkpython
Michael on Bluesky: @mkennedy.codes at bsky.app
Michael on Mastodon: mkennedy