Gevent and UI (real threads?)

337 views
Skip to first unread message

Ian Epperson

unread,
Feb 9, 2013, 1:44:09 PM2/9/13
to gev...@googlegroups.com
I've got a nifty little LAN game redirector I wrote using Gevent intended to run on OSX or Windows (Linux is a bonus).  It's extremely IO bound and works great from a command line, but with no interaction (quit, kick/ban, publish game, etc).  Now I'd like to add a UI to it and keep banging my head on problems of various approaches.


1) Just use the command line.  Dirt simple, but requires that I can do a gevent-friendly read from stdin - which doesn't seem to be possible on Windows (works great on OSX and Linux).


2) Curses is not available on Windows.  Drat.


3) Tkinter seems like a bit more weight, but is most widely available.  Unfortunately, it runs in its own mainloop and doesn't work well with gevent.  

3a) Make Tkinter green.  I managed to write my own mainloop which calls gevent.sleep frequently enough to function, but Tk does not return to this loop while any button on the interface is pressed or held down.  I saw some examples that performed a gevent.sleep during a Tkinter idle loop, but it either soaked up 100% CPU (sleep 0) or as not reactive enough (sleep > 0), and again it doesn't seem to be "idle" when a user is pressing a button.  Since these callbacks are coming from the Tk layer itself (or not), I think this approach a non-starter.

3b) Run Tkinter in a real thread.  I understand there's a bit of trickiness here and I'd have to ensure that gevent calls happend only after the logic thread starts up.  So, how to communicate between these threads?  Windows doesn't support named pipes and the firewall will get involved with a real socket.  Threading.queue and threading.event messages seem to be the way to go - I can imagine that the logic-to-UI messages could run through a threading.queue (maybe using one of the tricks in 3a to service them), but I'm not sure gevent will happily deal with UI-to-logic messages. Is there some trick to greening only half of a threading.queue?  Should the receiving end simply run in a tight loop with a gevent.sleep(0.2) or something?


4) Screw it, run a web server for control.  I'll still need some kind of really simple UI for a shutdown button, and I get to start monkeying around with Javascript to make the client work as needed.  I know it would work, but, bleh!


Any advice would be appreciated!

Ian.

--
This email is intended for the use of the individual addressee(s) named above and may contain information that is confidential, privileged or unsuitable for overly sensitive persons with low self-esteem, no sense of humor or irrational religious beliefs. If you are not the intended recipient, any dissemination, distribution or copying of this email is not authorized (either explicitly or implicitly) and constitutes an irritating social faux pas. Unless the word absquatulation has been used in its correct context somewhere other than in this warning, it does not have any legal or grammatical use and may be ignored. No animals were harmed in the transmission of this email, although the yorkshire terrier next door is living on borrowed time, let me tell you. Those of you with an overwhelming fear of the unknown will be gratified to learn that there is no hidden message revealed by reading this warning backwards, so just ignore that Alert Notice from Microsoft: However, by pouring a complete circle of salt around yourself and your computer you can ensure that no harm befalls you and your pets. If you have received this email in error, please add some nutmeg and egg whites and place it in a warm oven for 40 minutes. Whisk briefly and let it stand for 2 hours before icing.

Markus Thurlin

unread,
Feb 10, 2013, 6:03:06 PM2/10/13
to gev...@googlegroups.com
I just tried to make tkinter "green". I did not see any of the problems you described. The app is responsive, does not consume any visible CPU and does not block on interaction with buttons/texts. 
The mainloop runs 100 times per second. That seems to be enough for the UI, but it can perhaps be sluggish if it needs to share time with thousands of other greenlets and/or heavy IO. 

However, it should be good enough for any "command-and-control" UI. 

--
You received this message because you are subscribed to the Google Groups "gevent: coroutine-based Python network library" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gevent+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ian Epperson

unread,
Feb 10, 2013, 9:29:42 PM2/10/13
to gev...@googlegroups.com
Thanks for the feedback Markus.

root.update() works well on Windows, but on OSX does not return while the user is holding a button or while a pulldown menu is open (Python 2.7.1).

I've started my implementation using threads and two queues.  Gevent services its inbound threading.queue by running a loop to check for messages every so often (meh, but works) and I tried using that same method to check the inbound queue of Tkinter, but it consumed much more CPU than simply using the root.after command to continually check the queue (5% vs. 0.5% for 200ms checks! 100ms went to 10% and 1.0%).  It's workable, but it be much cleaner if I could get events back and forth.

Ian. 

Matias Guijarro

unread,
Feb 22, 2013, 6:11:51 PM2/22/13
to gev...@googlegroups.com
Hi,


Le lundi 11 février 2013 03:29:42 UTC+1, Ian E a écrit :
I've started my implementation using threads and two queues.  Gevent services its inbound threading.queue by running a loop to check for messages every so often (meh, but works) 

I would suggest to use an async watcher instead of running a loop to check for messages.

It is safe to share async watchers between threads. From the Tkinter thread you put an item
into the queue, then call the "send" method ; in the gevent thread, the async watcher callback
will be fired : you can read messages from the shared queue.

You can find information about async watchers on the mailing list otherwise see
gevent/threadpool.py for how to use it.

Hope this helps,
Matias.
Reply all
Reply to author
Forward
0 new messages