CabbageDevelopment / qasync

Python library for using asyncio in Qt-based applications.
BSD 2-Clause "Simplified" License
317 stars 45 forks source link

Integration in IPython #125

Open michaelcroquette opened 1 month ago

michaelcroquette commented 1 month ago

I'm tryng to replace quamash by qasync in our project (http://lneuhaus.github.io/pyrpl/). I managed to make it work without any problem with regular python but when using IPython I get an error. I was able to recreate it with the following lines:

from PyQt5 import QtWidgets      
import qasync   
APP = QtWidgets.QApplication(['test'])
LOOP = qasync.QEventLoop()

I get the error in the console:

[IPKernelApp] ERROR | Error in message handler Traceback (most recent call last): File "C:\Users\MichaelCroquette\anaconda3\envs\py312\Lib\site-packages\ipykernel\kernelbase.py", line 534, in dispatch_queue await self.process_one() File "C:\Users\MichaelCroquette\anaconda3\envs\py312\Lib\site-packages\ipykernel\kernelbase.py", line 517, in process_one t, dispatch, args = await self.msg_queue.get() ^^^^^^^^^^^^^^^^^^^^^^^^^^ RuntimeError: Task <Task pending name='Task-7' coro=<Kernel.dispatch_queue() running at C:\Users\MichaelCroquette\anaconda3\envs\py312\Lib\site-packages\ipykernel\kernelbase.py:534> cb=[_wrap_awaitable.<locals>.<lambda>() at C:\Users\MichaelCroquette\anaconda3\envs\py312\Lib\site-packages\tornado\gen.py:851, IOLoop.add_future.<locals>.<lambda>() at C:\Users\MichaelCroquette\anaconda3\envs\py312\Lib\site-packages\tornado\ioloop.py:699]> got Future <Future pending> attached to a different loop

I am using python 3.12.4, ipython 8.25.0, pyqt 5.15.10 and qasync 0.23.0.

michaelcroquette commented 1 month ago

I used conda to install qasync and ended up with version 0.23.0, I realized there are more recent versions so I reinstalled it with pip and got version 0.27.1 where the bug didn't appear. But now I get the RuntimeError: no running event loop but that's probably an issue from my code.

michaelcroquette commented 1 month ago

Ok I continued searching and understood that the issue was the already_running argument of the qasync.QEventLoop(). With version 0.27.1 of qasync when I enter :

from PyQt5 import QtWidgets      
import qasync   
APP = QtWidgets.QApplication(['test'])
LOOP = qasync.QEventLoop(already_running=True)

IPython crashes and send the following error: RuntimeError: asyncio.run() cannot be called from a running event loop which if I understand comes from IPython event loop interfering with the QEventLoop.

If I set the already_running argument to False, the event started by the application are never sent to the loop. What is the proper way to adapt the code in an IPython environment ? Thanks for your help.