Caller¶
Caller is a class that makes it easy to call code in different threads/tasks.
One caller instance is created per thread, and each of those instances can be retrieved by name using the Caller.get provided there is a running asynchronous event loop.
Threads¶
The caller manages a pool of worker threads (not related to anyio worker threads) or you can specify the name of a new thread which you can manage yourself. Each thread has its own anyio event loop in which the code will be called.
Most methods that perform execution return an async_kernel.Pending instance. The result can be obtained by awaiting it.
Usage by the kernel¶
The kernel uses two Caller instances; one each for shell and control. The shell thread event loop is normally the MainThread,
but is the thread wherever the kernel is started. The control event loop is always named ControlThread and is in the children of the shell caller.
The caller instances are stored on the kernel at kernel.callers[SocketID].
# A magic method provided by async kernel
%callers
Name Running Protected Thread
───────────────────────────────────────────────────────────────────────────────────────────
Shell ✓ 🔐 <_MainThread(MainThread, started 139952608534656)> ← current
Control ✓ 🔐 <Thread(Control, started daemon 139952535082688)>
from async_kernel import Caller
Caller()
Caller<Shell asyncio 🏃 running 1 child>
Example¶
This example requires ipywidgets!
import random
import time
import ipywidgets as ipw
outputs = {}
def my_func(n):
caller = Caller()
if not (out := outputs.get(caller)):
outputs[caller] = out = ipw.HTML(description=str(caller))
out.style.description_width = "220px"
display(out)
sleep_time = random.random() / 4
out.value = f"{n=:04d} sleeping {sleep_time * 1000:03.0f} ms"
time.sleep(sleep_time)
return n
async def run_forever():
n = 0
while True:
n += 1
yield Caller().to_thread(my_func, n)
async for fut in Caller().as_completed(run_forever()):
result = await fut
print(f"Finished: {result}", end="\r")
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
HTML(value='', description='Caller<async_kernel_caller asyncio 🏃 running >', style=HTMLStyle(description_width…
%callers
Name Running Protected Thread
──────────────────────────────────────────────────────────────────────────────────────────────────────
Shell ✓ 🔐 <_MainThread(MainThread, started 139952608534656)> ← current
Control ✓ 🔐 <Thread(Control, started daemon 139952535082688)>
✓ <Thread(async_kernel_caller, started daemon 139951911990976)>
✓ <Thread(async_kernel_caller, started daemon 139951895209664)>
✓ <Thread(async_kernel_caller, started daemon 139951878428352)>
✓ <Thread(async_kernel_caller, started daemon 139951643555520)>
✓ <Thread(async_kernel_caller, started daemon 139951626774208)>
✓ <Thread(async_kernel_caller, started daemon 139951609992896)>
✓ <Thread(async_kernel_caller, started daemon 139951375120064)>
✓ <Thread(async_kernel_caller, started daemon 139951358338752)>
✓ <Thread(async_kernel_caller, started daemon 139951341557440)>
✓ <Thread(async_kernel_caller, started daemon 139951106684608)>