What are the differences between asyncio
and Using the cothread Library
?
There are two concurrency frameworks that pythonSoftIOC supports, asyncio
and
Using the cothread Library
. This page details the differences between them and reasons why you
should use one over the other
See also
Use asyncio in an IOC for an example of how to use asyncio and pythonSoftIOC
The Similarities
Both frameworks are asynchronous concurrency frameworks, which means that they run in a single OS thread, and use lightweight coroutines/cothreads for concurrency. These are more deterministic and use less resources than OS threads, which makes them well suited to applications like pythonSoftIOC where many records may be processing concurrently. The biggest advantage is that only one coroutine runs at any one time. A coroutine will run until it yields control to another coroutine. This means that changes to shared state can only occur when it has yielded control, which reduces the need for mutexes that would be needed in threaded code.
The Differences
The main difference between the libraries is how a coroutine yields control.
asyncio
uses anasync def
which will yield control when theyawait
. Only anasync def
canawait
anotherasync def
, so functions that yield control are explicitly marked as such by the presence of theasync
keyword.Using the cothread Library
has theYield()
function which can be used in any ordinarydef
. The yield is implicit as you need to read the documentation/source code to find out if a function will yield control
For example, an on_update function written using cothread might be:
import cothread
from softioc import builder
def something_that_yields_control(value):
cothread.Sleep(0.1)
def update_ao(value):
something_that_yields_control(value)
print(value)
builder.aOut('AO', on_update=update_ao)
While the same example written using asyncio is:
import asyncio
from softioc import builder
async def something_that_yields_control(value):
await asyncion.sleep(0.1)
async def update_ao(value):
await something_that_yields_control(value)
print(value)
builder.aOut('AO', on_update=update_ao)
Note that because something_that_yields_control()
is an async def
,
update_ao()
needs to be too.
See also
https://glyph.twistedmatrix.com/2014/02/unyielding.html for a discussion on explicit vs implicit yield
Which to use
There are some questions to ask to help you choose which one to use:
If you run python2.7 then you need to use
Using the cothread Library
asasyncio
is python3 onlyIf you run on Windows then you need
asyncio
asUsing the cothread Library
doesn’t work on WindowsIf you need to integrate with a library that uses
asyncio
like one from aio-libs then useasyncio
If you need to turn a script using
cothread.catools
into an IOC then useUsing the cothread Library
In general, avoid mixing concurrency frameworks if you can. While it is possible
to mix asyncio
and Using the cothread Library
, it’s messy and tricky to get right. Better to
keep to one if possible.