Using library with asyncio

Python and python framework

Moderator: leecollings

Post Reply
Filip
Posts: 109
Joined: Thursday 03 November 2016 10:12
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Using library with asyncio

Post by Filip »

Hi,

I am developing a plugin based on a library that uses the python library asyncio.
My plugin uses already the treading mechanism as explained in https://github.com/domoticz/domoticz/bl ... hreaded.py.

From the asyncio documentation, it is clear that this can be used even in a thread by just using the asyncio.run() statement.

However when doing this, I always got an error "there is no current event loop in thread", while for the asyncio.run() there is no need to initialize a loop.

Any idea?

My thread-function looks like (concept)

Code: Select all

    def handleTasks(self):
        Domoticz.Debug('Entering tasks handler')

        try:
            while True:
                task = self.tasksQueue.get(block=True)

                if task is None:
                    Domoticz.Debug('Exiting task handler')
                    self.tasksQueue.task_done()
                    break

                Domoticz.Debug('Handling task: {}.'.format(task['Action']))
                if task['Action'] == 'Login':
                    try:
                        asyncio.run(my_routine_using_asyncio())
                    except Exception as err:
                        Domoticz.Debug('Login error: {}'.format(err))
pipiche
Posts: 2009
Joined: Monday 02 April 2018 20:33
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: France
Contact:

Re: Using library with asyncio

Post by pipiche »

We are using thread and asyncio extensively you might want to look here where we start the asyncio part

https://github.com/zigbeefordomoticz/Do ... ead.py#L73
Zigbee for Domoticz plugin / RPI3B+ / Electrolama ZZH-P / 45 devices

If the plugin provides you value, you can support me with a donation Paypal.

Wiki is available here.

Zigbee for Domoticz FAQ
Filip
Posts: 109
Joined: Thursday 03 November 2016 10:12
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Using library with asyncio

Post by Filip »

I am already suffering a while from a strange behavior. Just as example, I have 2 plugins: 1) BMW and 2) Husvqarna.

Husqvarna is using httpx (httpx.Client() - synchronous sessions). The BMW plugin is based on the bimmer_connected library, using httpx.AsyncClient() and asyncio.

All is running fine! Except when restarting the Husqvarna plugin, there are problems with the BMW plugin communication (managed by the bimmer_connected library).

In order to understand what is happening I used - by experiment - asyncio also in the bmw plugin:
___asyncio_plugin.py.txt
(58.99 KiB) Downloaded 4 times

In this implementation, the asyncio event loop is running in a thread inside the plugin, starting my main task by:

Code: Select all

self.async_loop.run_until_complete(self.async_main_task())
And the strange thing that happens when restarting the Husqvarna plugin, the asyncio event loop is closed. And even more strange is that the task (self.async_main_task()) itself is not finished, meaning that it cannot cause the end of the loop due "run_until_complete". This is proven as there is not any logging showing that the self.async_main_task() ends.

Code: Select all

2025-05-31 22:04:44.456 BMW X1: Asyncio event loop is about to close.
2025-05-31 22:04:44.457 BMW X1: Asyncio loop closed in isolated thread.
2025-05-31 22:04:44.457 BMW X1: Event loop cleared from thread context.
2025-05-31 22:04:44.457 BMW X1: Asyncio thread function finished.
In my understanding the Domoticz plugin management leads to threads being terminated or asyncio loops becoming unusable without Python-level exceptions.

Has anyone else faced such behavior? Is this a problem in Domoticz?

Thanks for your thoughts!
Currently the only workaround that I apply is restarting the BMW plugin after the Husqvarna plugin restarted.
However I would hope getting the root cause of the problem solved (if possible).

Btw: I have a third plugin that is using the Domoticz API with httpx (no sessions, just httpx.get()) and this has the same effect on the BMW plugin/bimmer_connected.
pipiche
Posts: 2009
Joined: Monday 02 April 2018 20:33
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: France
Contact:

Re: Using library with asyncio

Post by pipiche »

With the plugin Zigbee4Domoticz we are also using asyncio via the zigpy library fully relying on it.
what we are doing is to start a dedicated thread here https://github.com/zigbeefordomoticz/Do ... ead.py#L84

and then the thread create a new loop here https://github.com/zigbeefordomoticz/Do ... ead.py#L95

Hope it helps
Zigbee for Domoticz plugin / RPI3B+ / Electrolama ZZH-P / 45 devices

If the plugin provides you value, you can support me with a donation Paypal.

Wiki is available here.

Zigbee for Domoticz FAQ
Filip
Posts: 109
Joined: Thursday 03 November 2016 10:12
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Using library with asyncio

Post by Filip »

Thanks for your feedback.

This is exactly the principle I used... Start a thread --> creates the loop --> start the task with run_until_complete --> in my cased the task is running in endless loop to get instructions through queue...
___asyncio_plugin.py.txt
(58.99 KiB) Downloaded 8 times
  • L430: create thread
  • L647: create loop (in thread)
  • L653: async_loop.run_until_complete --> main task
  • L678 main task "async_main_task" (waiting for commands in the queue; running as long as plugin is not stopped)
When the problem happened, I can see that the async_main_task did not end as the last debug instruction on L740 is not happening, but the loop ends as we get into the block starting at L665 (without an exception that happened).

Of course I am not controlling what is happening inside the bimmer_connected library.

F
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest