Consider this contrived example: import asyncio async def main(): print(non_async_function()) def non_async_function(): # Syntax error due to "await". return await async_function() async def async_function(): return "foo" if __name__ == '__main__': asyncio.run(main()) Since the await keyword cannot be used in a non-async function, how do I await an awaitable from a non-async function? asyncio.run and asyncio.get_running_loop().run_until_complete don't work: RuntimeError: This event loop is already running. asgiref.async_to_sync also doesn't work: RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly. This problem comes up with chained decorators where a decorator can provide both async and sync variants using inspect.iscoroutinefunction -- but if one of the decorators doesn't do this, subsequent decorators will mistakenly assume they're wrapping a sync function. A sync decorator can guard against this by checking the result (assuming it needs to operate on the result before returning it): result = func(*args, **kwargs) if inspect.isawaitable(result): return sync_await(result) But how do I implement this sync_await in a way that uses the current async context with current context vars? Continue reading...