Advanced Topics
qtinter implements a logical asyncio event loop on top of a
physical Qt event loop, allowing Qt objects and asyncio coroutines
to run in the same thread and thus integrate seamlessly.
Best Practice
Clean-up
The using_asyncio_from_qt() context manager handles clean-up
automatically. The using_qt_from_asyncio() context manager
restores the default event loop policy upon exit; loop-level clean-up
is handled by asyncio.run().
If you create and manipulate a QiBaseEventLoop directly,
you should do the proper clean-up after it is no longer used. The
steps are:
Cancel all pending tasks.
Wait for all pending tasks to complete.
Run
asyncio.loop.shutdown_default_executor()(since Python 3.9).Call
asyncio.loop.close().
Steps 2-4 are coroutines and therefore must be run from within the event loop.
Note
At the point of clean-up, a Qt event loop may no longer exist and
is not creatable if QCoreApplication.exit() has been called.
Therefore the using_asyncio_from_qt() context manager runs
Steps 2-4 in a physical asyncio event loop.
Qt binding resolution
qtinter checks for the Qt binding used by the process
(interpreter) the first time a qtinter.QiBaseEventLoop()
is run. It remembers this binding afterwards.
If exactly one of PyQt5, PyQt6, PySide2 or PySide6 is
imported in sys.modules at the time of binding lookup,
it is chosen.
If none of the above modules are imported at the time of lookup,
the environment variable QTINTERBINDING is checked. If it is
set to one of PyQt5, PyQt6, PySide2 or PySide6,
that binding is used; otherwise, ImportError is raised.
If more than one supported binding modules are imported at the time of
lookup, ImportError is raised.