UIs in Python
interacting with an app, a python app, without too much dicking about
June 3, 2017 — February 13, 2023
Assumed audience:
Data scientists who think it might be easy to make a front end
Stream processing in python, especially for UIs. GUIs in python are a mess. Ultimately, I gave up trying to do anything non-trivial here. IMO the best way to get a live GUI in python is to use one that someone else made. This is a specialised and skilled area.
1 IO loop evented asynchrony
See asynchronous python for some fiddly details of the asynchrony itself.
Jakub’s example is clear, although the particular libraries he uses are not my favourites.
1.1 Web toolkits talking to python servers
One obvious use-case for all this evented stuff is to use the great GUI mind-share of our time, web engines talking to servers. The details of doing this oneself are tricky on both the client side and the server side. I would tend not to touch either of them myself because I have specialised my skillset elsewhere. Instead, I would use one of the fancy new dashboard systems that have arisen in the last couple of years. For exploratory data analysis and visualisation, these are pretty good and mostly python.
For other purposes, you might roll your own. Below are some systems I have used unsuccessfully to that end in the past.
Flexx attempts to provide more bells and whistles, including automatic widget generation and synchronisation from python, still using asyncio
.
Thrust renders a chromium window to look at your served code. I’m not 100% clear how it is substantially easier than just running a browser and a server.
brython interprets python using javascript.
There are many examples of rolling your own, using a classic webserver, or electron. Your adventure continues at javascript apps.
1.2 Gradio
Targeting ML uses: Gradio “…is the fastest way to demo your machine learning model with a friendly web interface so that anyone can use it, anywhere!”
Limited in scope but well-supported.
1.3 Bizarre hybrids of Web GUIs and user interfaces
DIY python web gui by David Baird:
In this howto, I explain the following concepts:
How to launch a GUI toolkit in a separate thread, and how to communicate with this thread.
How to embed a web browser inside the GUI, and how to communicate with this embedded web browser without using sockets. By not using sockets, we don’t have to worry about socket security, and we don’t have to worry about allocating a socket. […] In other words, we will have AJAX-like […] functionality to communicate with Python but without actually having to use AJAX.
2 wxPython
2.1 RAD/gui builders
2.2 macOS Framework python
You are getting errors like This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.
This probably means your python virtual environment is not a framework python virtualenv. What is a “framework python”? It’s highly unlikely you are being paid enough to care what a framework build of python is. I certainly am not.
You can work around it with laborious wrapper hacks, or use anaconda python
or your system python.
For python 3 you can use the native virtual environment, venv, now a built-in virtual python environment system in python 3. It doesn’t support python 2 but fixes various problems, e.g. supporting macOS Framework python and is covered by the python docs in the python virtual environment introduction.
If there are other solutions and they are one iota more complex than this I don’t want to hear about them thanks.
3 tkinter
tkinter is well-worn and sturdy dating back to the 90s. It’s a wrapper around the tcl
gui toolkit, called tk
. If you want to make something simple, it’s not too bad.
It can integrate with tornado.
Beware of the many class renames between python 2 and 3.
3.1 Cute examples
It looks primitive, but you can get a long way.
E.g. dynamic collapsible content:
def toggle(self):
if bool(self.show.get()):
self.sub_frame.pack(fill="x", expand=1)
self.toggle_button.configure(text='-')
else:
self.sub_frame.forget()
self.toggle_button.configure(text='+')
Or see snake, including sprites and canvas with collision detection.
There is an even-simpler GUI thing called EasyGUI which attempts to make GUI code less awkward. I think it is mostly about modal boxes and is not as smooth for visualisation of information.
3.2 intros
- tkdocs is an incomplete but pretty good book on tkinter, also explaining the perl and ruby versions
- effbot tkinter guide is good and differently incomplete and slightly outdated.
- See Tkinter example for controlling a robot
- NMT Tkinter reference is in-depth but outdated, missing many renames. Still the best, IMO.
- The official tk docs are complete, but referencey and written for
tcl
rather than python. - the official python tkinter docs are fine but especially incomplete.
3.3 tips
- For sorta-native look and feel you use
ttk
which introduces styles and themes. Neither of these are obvious. - Control variables provide convenient data-syncing accessors for what I will loosely call “scalar types”. Think of them as primitive controllers.
- There are two layout managers,
pack
andgrid
. If you come from an HTML background the former is somewhat like a mildly crippled version of block-layout and the latter somewhat more like HTML tables. You can’t mix them within a single parent widget, but you can freely nestFrame
widgets with different interior layouts.
4 cefpython
cefpython embeds a chrome webview in python; it also supports bidirectional IPC between python and javascript. Its concurrency constructs look… idiosyncratic.
5 QT
Want a somewhat more modern look, and modern conveniences. Qt5 is, by all accounts, pretty good. The language bindings keep changing though, and betwixt qt5 and qt4 lies a chasm which many projects have failed to cross. For QT directly apparently one should use pyotherside? Although I now see people using qtpy as a unifying abstraction layer over all the other unifying abstraction layers. Maybe if I do that the pain will go away.
To make everything easier, perhaps one should use one of the mildly hip meta-frameworks, such as enaml, which handles asynchronous widget binding and such, and enaml-native, which attempts to create mobile-friendly react-native-esque applications.
6 Dear PyGui
- hoffstadt/DearPyGui: Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies
- Dear PyGui’s Documentation — Dear PyGui documentation
Dear PyGui is an easy-to-use, dynamic, GPU-Accelerated, cross-platform graphical user interface toolkit(GUI) for Python. It is “built with” Dear ImGui.
Features include traditional GUI elements such as buttons, radio buttons, menus and various methods to create a functional layout.
Additionally, DPG has an incredible assortment of dynamic plots, tables, drawings, debugger, and multiple resource viewers.
DPG is well suited for creating simple user interfaces as well as developing complex and demanding graphical interfaces.
DPG offers a solid framework for developing scientific, engineering, gaming, data science and other applications that require fast and interactive interfaces.
7 Kivy
Multitouch, GPU-friendly, mobile-friendly (and a little bit retro in the design style if not the technologies) kivy, a complete app environment.
8 Nuklear
Immediate mode is a hip minimalist alternative to GUI toolkits. Jari Komppa’s tutorial explains:
In typical GUI applications you create a bunch of widgets, they get displayed somehow, you query the widgets for information, you send messages and data to said widgets, and finally clean things up after you’re done. Some parts of the above is usually done using some kind of visual editor, but the result is usually tons and tons of code all over the place.
This is ok for most applications, but not so convenient for games or other frame-by-frame realtime applications. So, instead of having one place for init, another for ui callbacks, and a third for cleanup, IMGUI can be as simple as this:
In practice things get a little bit more complicated, but not much.
The magic here is that the call to button will perform everything the widget would be expected to do at any single time, including the rendering of the visible widget. There’s a bit of global data that’s shared by all of the widgets that enables them to work.
nuklear is a popular one, that has python bindings called pynuklear. Dear Imgui is another, which has actually too many python bindings. pyimgui and hoffstadt/DearPyGui seem active.
9 Text mode
You know what is boring? fighting concurrency problems. Text is so fast you can ignore that. Mostly. If you want. Probably sometimes. Python has curses in the standard library. But that is pretty low level and tedious, as you can see from the tutorial. npyscreen provides an ‘editable form’ type interface. urwid is more event-oriented, and has pluggable event loops. But fewer neat widgets than npyscreen.
10 Incoming
Scripted forms provides a simple scientific-style (no frills no fuss) GUI from markdown. based on jupyter.
Param seems to do something with parameterization of objects and works with e.g. cool semi-automated dashboards.