Server green modes#
PyTango server API from version 9.2.0 supports two green modes:
Gevent
and Asyncio
.
Both can be used in writing new device servers in an asynchronous way.
Note
If your device server has multiple devices they must all use the same green mode.
Warning
These green modes disable Tango’s device server serialisation,
i.e., tango.SerialModel.NO_SYNC
is automatically passed to tango.Util.set_serial_model()
,
when the device server starts. From those docs: “This is an exotic kind of serialization and
should be used with extreme care only with devices which are fully thread safe.”
gevent mode#
This mode lets you convert your existing devices to asynchronous devices
easily. You just add green_mode = tango.GreenMode.Gevent
line to your device
class. Consider this example:
class GeventDevice(Device):
green_mode = tango.GreenMode.Gevent
Every method in your device class will be treated as a
coroutine implicitly. This can be beneficial, but also potentially dangerous
as it is a lot harder to debug. You should use this green mode with care.
Gevent
green mode is useful when you don’t want to
change too much in your existing code (or you don’t feel comfortable with
writing syntax of asynchronous calls).
Another thing to keep in mind is that when using Gevent
green mode is that the Tango monitor lock is disabled, so the client requests can
be processed concurrently.
Greenlets can also be used to spawn tasks in the background.
asyncio mode#
The way asyncio green mode on the server side works is it redirects all user
code to an event loop. This means that all user methods become coroutines, so
in Python > 3.5 you should define them with async
keyword.
This also means that in order to convert existing code of your devices
to Asyncio
green mode you will have to introduce
at least those changes. But, of course, to truly benefit from this green mode
(and asynchronous approach in general), you should introduce more far-fetched changes!
The main benefit of asynchronous programing approach is that it lets you
control precisely when code is run sequentially without interruptions and
when control can be given back to the event loop. It’s especially useful
if you want to perform some long operations and don’t want to prevent clients
from accessing other parts of your device (attributes, in particular). This
means that in Asyncio
green mode there is no monitor
lock!
The example below shows how asyncio can be used to write an asynchronous Tango device:
1# SPDX-FileCopyrightText: All Contributors to the PyTango project
2# SPDX-License-Identifier: LGPL-3.0-or-later
3"""Demo Tango Device Server using asyncio green mode"""
4
5import asyncio
6from tango import DevState, GreenMode
7from tango.server import Device, command, attribute
8
9
10class AsyncioDevice(Device):
11 green_mode = GreenMode.Asyncio
12
13 async def init_device(self):
14 await super().init_device()
15 self.set_state(DevState.ON)
16
17 @command
18 async def long_running_command(self):
19 self.set_state(DevState.OPEN)
20 await asyncio.sleep(2)
21 self.set_state(DevState.CLOSE)
22
23 @command
24 async def background_task_command(self):
25 loop = asyncio.get_event_loop()
26 future = loop.create_task(self.coroutine_target())
27
28 async def coroutine_target(self):
29 self.set_state(DevState.INSERT)
30 await asyncio.sleep(15)
31 self.set_state(DevState.EXTRACT)
32
33 @attribute
34 async def test_attribute(self):
35 await asyncio.sleep(2)
36 return 42
37
38
39if __name__ == "__main__":
40 AsyncioDevice.run_server()