Basic usage¶
Convert a synchronous function to asynchronous¶
Add the asyncify decorator to an existing synchronous function. Its logic is
unchanged; calling it now returns an awaitable.
import asyncio
from unblock import asyncify
@asyncify
def my_sync_func():
... # do something blocking
asyncio.run(my_sync_func())
Use a process pool¶
For CPU-bound work, run on a process pool instead of threads. This works as a decorator on any importable (module-level) function.
from unblock import asyncify
@asyncify(executor="process")
def cpu_bound(n):
return sum(i * i for i in range(n))
You may also pass your own executor instance:
from concurrent.futures import ThreadPoolExecutor
from unblock import asyncify
pool = ThreadPoolExecutor(max_workers=4)
@asyncify(executor=pool)
def work():
...
Convert methods and properties of a class¶
Synchronous methods and properties can be converted as well. async_property
runs the getter off the loop; async_cached_property does the same but caches
the result (computed once, even under concurrent awaits).
import asyncio
from unblock import asyncify, async_property, async_cached_property
class MyClass:
@asyncify
def my_sync_method(self):
...
@async_property
def prop(self):
... # returned value, awaited at access: await obj.prop
@async_cached_property
def cached_prop(self):
... # computed once, then cached
Convert all synchronous methods of a class¶
Applying @asyncify to a class converts its public synchronous instance
methods. Methods starting with an underscore, static methods, class methods, and
methods that are already async are left unchanged.
from unblock import asyncify
@asyncify
class MyClass:
def my_sync_func(self):
...
def _private(self):
... # not converted (private)
async def already_async(self):
... # unchanged
Use include or exclude to control exactly which methods are converted:
@asyncify(exclude=["validate"])
class Client:
def fetch(self):
... # converted
def validate(self):
... # stays synchronous
Note
When @asyncify is used on a class, only methods defined on that class are
converted; inherited methods are not. To wrap an existing class without
editing it, use the mixins described in the API page.
Advanced usage¶
See the API page for the mixins, configuration, and lifecycle helpers, and the Caveats page for important constraints.