[Matplotlib-users] Asyncio, Tk, and matplotlib

Thomas Caswell tcaswell at gmail.com
Thu Feb 23 21:07:56 EST 2017


Sorry I don't have time to write out a longer answer (with, you know,
working code), but a of couple of rough thoughts from recent experience.

 - all GUI stuff must happen on the main thread (if you do threads), but
for some backends `draw_idle()` maybe thread safe.
 - for asyncio no blocking part of the task should be slower than 1/10 a
second (that is the time between subsequent calls to `yield
from`/`yield`/`await`).  Anything slower and you will need to push it out
of the main thread/process.  It brings a bunch of complexity, but I would
look at something like dask.  The futures look to have a
`add_done_callback` method which you can use to bridge to an asyncio.Event
that you can await on, (although you might run into some tornado vs asyncio
issues).  Looks like someone has already done the work of hiding
multiprocess behind asyncio (https://github.com/dano/aioprocessing). Would
not go with threads unless you have a lot of gil releasing code.
 - integrating asyncio and GUIs are about the same problem as integrating
GUIs and the command line, you have two infinite loops that both want to
run the show (and block while waiting for the slow human).  I have been
using https://github.com/NSLS-II/bluesky/blob/master/bluesky/utils.py#L684 to
good effect at my day-job for keeping figures alive under asyncio, but we
are mostly waiting for (motion control related) network / motion.  You
install a self-perpetuating 'call_later' on to the asyncio event loop that
drains the GUI events (which lets all of their callbacks run and re-draws
the figure).
 - A super embarrassing (but functional) qt example is where I use qt
threads + ipyparallel is
https://github.com/tacaswell/leidenfrost/blob/master/leidenfrost/gui/proc_gui.py
In
this case I let the GUI event loop run the show.

Tom



On Thu, Feb 23, 2017 at 3:45 PM Ludwig Schwardt <ludwig.schwardt at gmail.com>
wrote:

> Hi Juan,
>
> Funny that you should mention it... I was busy with the exact same thing
> today :-)
>
> It is as you said: the matplotlib GUI has to run on the main thread. The
> trick seems to be to start the asyncio loop in a second background thread
> and communicate with the GUI running on the main thread via a queue. I
> found this <http://stackoverflow.com/a/34882411> StackOverflow answer
> very helpful.
>
> As an aside, I eventually ditched asyncio for an even simpler threading +
> queue solution (being stuck in Python 2.7...).
>
> Cheers,
>
> Ludwig
>
> P.P.S. I have an old matplotlib GUI app that used to disable the button
> during the long-running task (run from the on_clicked callback) to indicate
> when the GUI becomes available again. This behaviour does not seem to work
> anymore on modern matplotlib, hence my need to investigate background
> threads :-)
>
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users at python.org
> https://mail.python.org/mailman/listinfo/matplotlib-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20170224/4f55ddf1/attachment.html>


More information about the Matplotlib-users mailing list