Use asyncio in an IOC

Creating an IOC shows how to create a pythonSoftIOC using the Using the cothread Library library. This page shows how to create one using asyncio

See also

What are the differences between asyncio and cothread? for the differences and why you would use one over the other

Example IOC

# Import the basic framework components.
from softioc import softioc, builder, asyncio_dispatcher
import asyncio

# Create an asyncio dispatcher, the event loop is now running
dispatcher = asyncio_dispatcher.AsyncioDispatcher()

# Set the record prefix
builder.SetDeviceName("MY-DEVICE-PREFIX")

# Create some records
ai = builder.aIn('AI', initial_value=5)
ao = builder.aOut('AO', initial_value=12.45, always_update=True,
                  on_update=lambda v: ai.set(v))

# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit(dispatcher)

# Start processes required to be run after iocInit
async def update():
    while True:
        ai.set(ai.get() + 1)
        await asyncio.sleep(1)

dispatcher(update)

# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())

The dispatcher is created and passed to iocInit(). This is what allows the use of asyncio functions in this IOC. It contains a new event loop to handle this.

The async update function will increment the value of ai once per second, sleeping that coroutine between updates. Note that we pass this coroutine to the dispatcher, which will execute it in the dispatcher’s own event loop and not in the main event loop. It also provides some logging if exceptions occur.

This IOC will, like the one in Creating an IOC, leave an interactive shell open. The values of the PVs can be queried using the methods defined in the softioc.softioc module.

Asynchronous Channel Access

PVs can be retrieved externally from a PV in an asynchronous manner by using the aioca module. It provides await-able implementations of caget, caput, etc. See that module for more information.