{"id":1501,"library":"greenback","title":"Greenback","description":"Greenback is a Python library that enables calling asynchronous code from a synchronous context within an active `asyncio` or `Trio` event loop. It bridges the gap between synchronous and asynchronous programming, allowing for gradual migration of codebases and interoperability with async-unaware libraries. The current version is 1.3.0, and it maintains a focused release cadence as a small, specialized utility built on `greenlet`.","status":"active","version":"1.3.0","language":"python","source_language":"en","source_url":"https://github.com/oremanj/greenback","tags":["async","asyncio","trio","concurrency","greenlet","synchronous","bridge"],"install":[{"cmd":"pip install greenback","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core dependency for coroutine switching. Greenback is built on top of it.","package":"greenlet","optional":false}],"imports":[{"note":"Primary import for all functionalities.","symbol":"greenback","correct":"import greenback"},{"note":"Must be awaited as it sets up the greenlet context within an async task.","wrong":"greenback.ensure_portal() (without await)","symbol":"ensure_portal","correct":"await greenback.ensure_portal()"},{"note":"Used to 'await' an async function from a synchronous context where `await` keyword is not allowed.","wrong":"await async_function() (in sync code)","symbol":"await_","correct":"greenback.await_(async_function())"},{"note":"Runs a synchronous function with a portal, useful for scoping performance impact.","symbol":"with_portal_run_sync","correct":"greenback.with_portal_run_sync(sync_function)"}],"quickstart":{"code":"import asyncio\nimport greenback\n\n# An async function we want to call from sync code\nasync def fetch_data(item_id):\n    print(f\"[Async] Fetching data for {item_id}...\")\n    await asyncio.sleep(0.1) # Simulate I/O\n    return f\"Data for {item_id}\"\n\n# A synchronous function that needs to call an async function\ndef process_item(item_id):\n    print(f\"[Sync] Processing item {item_id}\")\n    # Call the async function from sync context using greenback.await_\n    data = greenback.await_(fetch_data(item_id))\n    print(f\"[Sync] Received: {data}\")\n    return data\n\n# The main async entry point\nasync def main():\n    # Ensure a greenback portal is set up for this task\n    await greenback.ensure_portal()\n    print(\"Portal ensured.\")\n\n    # Call the synchronous function that will use greenback\n    result = process_item(\"A123\")\n    print(f\"Main task received: {result}\")\n\n    # Example using with_portal_run_sync\n    def another_sync_task():\n        print(\"[Sync 2] Starting another sync task.\")\n        result2 = greenback.await_(fetch_data(\"B456\"))\n        print(f\"[Sync 2] Got: {result2}\")\n        return result2\n\n    final_result = greenback.with_portal_run_sync(another_sync_task)\n    print(f\"Main task got final result: {final_result}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates how to use `greenback` to call an `async` function (`fetch_data`) from a regular `sync` function (`process_item`, `another_sync_task`) within an `asyncio` event loop. First, `await greenback.ensure_portal()` is called in the main async task to set up the necessary `greenlet` context. Then, `greenback.await_()` is used in the synchronous functions to execute the async calls. The `with_portal_run_sync` helper is also shown for explicit portal scoping."},"warnings":[{"fix":"Thoroughly test C extension modules when used in a `greenback`-enabled context. Such issues often indicate a bug in the extension module itself, which `greenback` merely exposes.","message":"Greenback works by manipulating the C stack via `greenlet`. Poorly-behaved C extension modules that violate Python's assumption that objects are fully heap-allocated might crash when used with `greenback`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Avoid using `greenback.await_()` in these specific contexts. Refactor your code to perform async operations outside of finalizers, signal handlers, or weakref callbacks.","message":"Calling `greenback.await_()` inside Python finalizers (`__del__` methods), signal handlers, or weakref callbacks is explicitly unsupported and can lead to unexpected behavior or crashes.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `greenback.with_portal_run()` or `greenback.with_portal_run_sync()` to explicitly scope the portal's lifetime to only the necessary portion of a task, minimizing performance impact.","message":"Setting up a `greenback` portal (e.g., via `await greenback.ensure_portal()`) incurs a minor performance overhead for the task it's enabled on, as each task step passes through `greenback`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"When using `asyncio`, you must explicitly call `await greenback.ensure_portal()` in each task that intends to use `greenback.await_()`. Do not rely on automatic portal propagation for `asyncio`.","message":"The `greenback.with_portal_run_tree()` and other portal propagation functions designed for child tasks only work with the `Trio` event loop, not with `asyncio`, due to `asyncio`'s different task model and lack of necessary instrumentation features.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always `await` `greenback`'s asynchronous functions to ensure they execute correctly and yield their intended results.","message":"Calling `greenback`'s asynchronous functions (e.g., `with_portal_run_sync`, `ensure_portal`) without `await`ing them will result in a `RuntimeWarning` and the function will not execute as intended, instead returning an unawaited coroutine object.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always `await` `greenback`'s coroutine functions, such as `greenback.with_portal_run_sync()`, when you intend to execute them and obtain their result. For example, use `await greenback.with_portal_run_sync(...)`.","message":"Calling coroutine functions such as `greenback.with_portal_run_sync()` without `await`ing them will result in a `RuntimeWarning: coroutine was never awaited` and the coroutine object being returned instead of its intended result.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'1.3.0':50 'activ':18 'allow':33 'async':43,66 'async-unawar':42 'asynchron':10,31 'asyncio':19,67 'bridg':25,72 'built':63 'cadenc':57 'call':9 'code':11 'codebas':38 'concurr':69 'context':15 'current':47 'enabl':8 'event':22 'focus':55 'gap':27 'gradual':35 'greenback':1,2 'greenlet':65,70 'interoper':40 'librari':6,45 'loop':23 'maintain':53 'migrat':36 'program':32 'python':5 'releas':56 'small':60 'special':61 'synchron':14,29,71 'trio':21,68 'unawar':44 'util':62 'version':48 'within':16","created_at":"2026-04-09T03:50:39.362433+00:00","updated_at":"2026-04-16T15:28:15.378320+00:00","problems":[{"fix":"Ensure your synchronous code using greenback.await_() is called from within an active asyncio task after a portal has been set up, typically by wrapping the entry point in `asyncio.run()` or ensuring `await greenback.ensure_portal()` has been called in the async task.","cause":"Greenback requires an active asyncio or Trio event loop to re-enter asynchronous code from a synchronous context, and this error occurs when an attempt is made to use greenback.await_() or similar functions without a loop being currently active in the thread.","error":"RuntimeError: no running event loop"},{"fix":"Verify that the argument passed to `greenback.await_()` is indeed an awaitable (e.g., the result of calling an `async` function, like `asyncio.sleep(0)` instead of `asyncio.sleep`).","cause":"This error can occur when `greenback.await_()` is called with an expression that does not return an awaitable object (e.g., `None` instead of a coroutine or future), often due to a misconfigured or improperly called asynchronous function.","error":"TypeError: object NoneType can't be used in 'await' expression"},{"fix":"Install the greenback library using pip: `pip install greenback` or ensure your virtual environment is activated and greenback is installed within it.","cause":"This error indicates that the 'greenback' package is not installed in the Python environment being used, or the Python environment is not correctly configured.","error":"ModuleNotFoundError: No module named 'greenback'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"1.3.0","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/oremanj/greenback","docs":null,"changelog":null,"pypi":"https://pypi.org/project/greenback/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["http-networking","observability","web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-27","next_check":"2026-07-28","install_tag":"verified"}}