{"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":"en","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"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}