freshcrate
Home > Frameworks > greenback

greenback

Reenter an async event loop from synchronous code

Description

greenback: reenter an asyncio or Trio event loop from synchronous code ====================================================================== .. image:: https://img.shields.io/pypi/v/greenback.svg :target: https://pypi.org/project/greenback :alt: Latest PyPI version .. image:: https://img.shields.io/badge/docs-read%20now-blue.svg :target: https://greenback.readthedocs.io/en/latest/?badge=latest :alt: Documentation status .. image:: https://github.com/oremanj/greenback/actions/workflows/ci.yml/badge.svg :target: https://github.com/oremanj/greenback/actions/workflows/ci.yml :alt: Automated test status .. image:: https://codecov.io/gh/oremanj/greenback/branch/master/graph/badge.svg :target: https://codecov.io/gh/oremanj/greenback :alt: Test coverage .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/ambv/black :alt: Code style: black .. image:: http://www.mypy-lang.org/static/mypy_badge.svg :target: http://www.mypy-lang.org/ :alt: Checked with mypy Python 3.5 introduced ``async``/``await`` syntax for defining functions that can run concurrently in a cooperative multitasking framework such as ``asyncio`` or `Trio <https://trio.readthedocs.io/>`__. Such frameworks have a number of advantages over previous approaches to concurrency: they scale better than threads and are `clearer about control flow <https://glyph.twistedmatrix.com/2014/02/unyielding.html>`__ than the implicit cooperative multitasking provided by ``gevent``. They're also being actively developed to explore some `new ideas about concurrent programming <https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/>`__. Porting an existing codebase to ``async``/``await`` syntax can be challenging, though, since it's somewhat "viral": only an async function can call another async function. That means you don't just have to modify the functions that actually perform I/O; you also need to (trivially) modify every function that directly or indirectly calls a function that performs I/O. While the results are generally an improvement ("explicit is better than implicit"), getting there in one big step is not always feasible, especially if some of these layers are in libraries that you don't control. ``greenback`` is a small library that attempts to bridge this gap. It allows you to **call back into async code from a syntactically synchronous function**, as long as the synchronous function was originally called from an async task (running in an asyncio or Trio event loop) that set up a ``greenback`` "portal" as explained below. This is potentially useful in a number of different situations: * You can interoperate with some existing libraries that are not ``async``/``await`` aware, without pushing their work off into another thread. * You can migrate an existing program to ``async``/``await`` syntax one layer at a time, instead of all at once. * You can (cautiously) design async APIs that block in places where you can't write ``await``, such as on attribute accesses. ``greenback`` requires Python 3.8 or later and an implementation that supports the ``greenlet`` library. Either CPython or PyPy should work. There are no known OS dependencies. Quickstart ---------- * Call ``await greenback.ensure_portal()`` at least once in each task that will be using ``greenback``. (Additional calls in the same task do nothing.) You can think of this as creating a portal that will be used by future calls to ``greenback.await_()`` in the same task. * Later, use ``greenback.await_(foo())`` as a replacement for ``await foo()`` in places where you can't write ``await``. * If all of the places where you want to use ``greenback.await_()`` are indirectly within a single function, you can eschew the ``await greenback.ensure_portal()`` and instead write a wrapper around calls to that function: ``await greenback.with_portal_run(...)`` for an async function, or ``await greenback.with_portal_run_sync(...)`` for a synchronous function. These have the advantage of cleaning up the portal (and its associated minor performance impact) as soon as the function returns, rather than leaving it open until the task terminates. * For more details and additional helper methods, see the `documentation <https://greenback.readthedocs.io>`__. Example ------- Suppose you start with this async-unaware program: .. code-block:: python import subprocess def main(): print_fact(10) def print_fact(n, mult=1): """Print the value of *n* factorial times *mult*.""" if n <= 1: print_value(mult) else: print_fact(n - 1, mult * n) def print_value(n): """Print the value *n* in an unreasonably convoluted way.""" assert isinstance(n, int) subprocess.run(f"echo {n}", shell=True) if __name__ == "__main__": main() Using ``greenback``, you can change i

Release History

VersionChangesUrgencyDate
1.3.0Imported from PyPI (1.3.0)Low4/21/2026
v1.3.0Tag v1.3.0Low12/23/2025
v1.2.1Tag v1.2.1Low2/20/2024
v1.2.0Tag v1.2.0Low2/8/2024
v1.1.2Tag v1.1.2Low12/29/2023
v1.1.1Tag v1.1.1Low3/1/2023
v1.1.0Tag v1.1.0Low1/5/2022
v1.0.0Tag v1.0.0Low11/24/2021
v0.3.0Tag v0.3.0Low10/13/2020
v0.2.0Tag v0.2.0Low6/29/2020
v0.1.0Tag v0.1.0Low5/2/2020

Dependencies & License Audit

Loading dependencies...

Similar Packages

trioA friendly Python library for async concurrency and I/O0.33.0
sniffioSniff out which async library your code is running under1.3.1
python-socksProxy (SOCKS4, SOCKS5, HTTP CONNECT) client for Python2.8.1
blockbusterUtility to detect blocking calls in the async event loop1.5.26
txaioCompatibility API between asyncio/Twisted/Trollius25.12.2