Skip to main content

Experimenting with Shiny for Python

Shiny is a free, open-source, low-code utility for creating interactive figures that can be deployed to a website.  R coders have been using Shiny and loving it since it was created in 2012.   I personally am a Python coder at heart, though I have been learning R and Shiny steadily for the past year or so.  I’ve been impressed by how effective and intuitive Shiny is; indeed I’ve found that Shiny compares very favorably to interactive plotting tools for Python.  So, you can imagine how excited I was to see that Shiny is now available to Python in an “alpha” test status.  Here is what I learned getting started.

Initial Impressions  

Needless to say, I “nerded out” a bit when I heard that Shiny was coming to Python.  I looked at all their examples online , scrolled through their documentation, and I even attended the recent ShinyConf 2023 conference.  And of course, I also installed Shiny for Python on my machine.

I use Anaconda’s Python distribution because I appreciate their package management system. Installing Shiny for Python was as simple as installing any standard Python library; I created a new conda environment to isolate my experimental installation and then executed the following command in my terminal:

conda install shiny

And I was ready to go!

I started by simply copying one of the basic examples on the Shiny for Python website to my computer and running it.  As an astrophysicist by training, I was particularly interested in exploring the “orbit-simulation” example on the Shiny for Python website, which performs calculations that Python is better suited for than R.

If you have a file called app.py that contains your Shiny app, you can run it by typing the following command in your terminal:

shiny run –reload app.py

This will start a local Shiny server on your machine and make your app available in the browser at http://localhost:8000/.

My first Python + Shiny app

My idea was to create an interactive map of the Earth showing earthquake and volcano locations where the symbol size was defined by an attribute in the data set.  My interface would allow the user to choose between different attributes and show/hide each of the data sets.  I also wanted to include a histogram of the selected attribute for both the earthquakes and volcanoes.

I used Google’s Dataset Search tool to find two data sets with latitude and longitude coordinates to make the map: earthquake data from USGS and volcano data from The Smithsonian Institute.

As is my usual process, I started in a Jupyter notebook to create static version of the plots.  The histograms were straightforward and easy to produce using matplotlib.  For the map, I explored a few different options.  There is an example online using ipyleaflet with Shiny for Python to display a map.  I began there and enjoyed the interactivity and customization available with ipyleaflet maps, but I quickly realized that ipyleaflet would not allow me to overplot the many thousands of earthquakes on the map.  I then switched to cartopy, which is a great Python utility for making static maps.  This worked very well, but I was missing the zoom and pan features that were available in ipyleaflet.  While I could have built this type of interaction into Shiny, I wanted to explore existing solutions.  Then I remembered that our good old friend Plotly can produce scatterplots on top of maps with mapbox.

For those who aren’t familiar with Plotly, this is another fantastic library for creating interactive figures in Python, R and Javascript.   Just as it does when using R, Shiny works very nicely with Plotly and Python.  In this workflow, Shiny can be used to handle the user interface and layout of the figures, while Plotly is used to generate figures that enable the typical pan, zoom, tooltips, and other features.

I followed an example including Plotly with Shiny for Python; Plotly and ipyleaflet connect to Shiny as “widgets” using the py-shinywidgets package, which in turn uses the ipywidgets package.  Though I could have built the histograms in Plotly also, I decided to keep them in matplotlib to test the functionality in Shiny.

Here is the final result:

The code is available on my GitHub repo here and the live version is hosted on shinyapps.io here.  Overall, I was very pleased with the result!

I also discovered why Shiny for Python is currently in alpha testing

Though I am happy with the shiny app I created in this test, there were some pain points in the development process.  I was surprised how smoothly everything worked on my local machine.  The issues began to crop up when I wanted to host my app online.

Shiny, unlike some other Python interactive tools, does not produce a stand-alone .html file that can be hosted on your personal website or static hosting sites like GitHub pages.   There is good reason for this, as I also discussed in my previous Shiny blog post.  In short, Shiny handles all the data manipulation on the server side and only exposes the plots to the users on the website.  This protects data, but also requires a server to share your app with the world.  Fortunately, Posit provides a free Shiny server at shinyapps.io that is very user friendly to work with.

In my first attempt to deploy my app on shinyapps.io, the app died right after the page loaded.  After inspecting the logs and documentation, I discovered that shinyapps.io only supports Python versions 3.7.13, 3.8.13, 3.9.13, and I was working with version 3.10.9 on my local machine.   I created a conda environment with Python version 3.9.13, installed the necessary libraries, and then hit the same error locally.  After some googling I discovered that I specifically needed version 7.7.3 of ipywidgets in order to avoid the error.   After downgrading to that version, the app ran without errors.  I then specified explicitly which packages and which versions are required in my app using a requirements.txt file and was able to deploy the app successfully on shinyapps.io.

As an aside, I also tried to deploy a cartopy version of my app, without using py-shinywidgets.  This also failed on shinyapps.io, but without any obvious errors that I could discern.  It appears that the error came from including features such as continent boundaries, oceans, and lakes on the map, but I did not find any workaround or way to diagnose the issue, other than to simply remove the background map.  If you encounter this as well and solve it, please let me know!

But hey, this is an alpha test after all.  I was prepared to encounter issues, and I was happily surprised at how few there were.  In the end, I managed to create and deploy a functional app without much trouble.  I’m sure Shiny for Python and its integration with shinyapps.io will only become better as the developers continue their good work.

Why you should try Shiny for Python

For R coders looking for inroads to learning Python, this is a great motivator for getting started.  For Python coders who want to develop interactive visualizations, Shiny is definitely something to investigate along with other utilities that I covered in a previous blog post.  In fact, I plan to continue using Shiny as a “go to” tool for  quick prototyping of interactive visualizations in Python.  Here’s why:

  • Shiny has very smooth integration with the HTML, CSS, and Javascript elements of the webpage, and allows developers a lot of functionality in the look and feel of the app. It is true that like other interactive Python tools, Shiny has a standard look.  But Shiny also gives easy access to customizing styles and including extra bits of HTML, CSS and Javascript code, which is much harder or impossible in other libraries such as Bokeh and Plotly.
  • The documentation and examples are typically excellent in Shiny. The Shiny for Python documentation side is not yet as developed as the R documentation, but I assume that will improve.  And I imagine that most of the features available in Shiny for R will also be available in Shiny for Python.
  • I personally find the Shiny code structure very intuitive and streamlined – much more than many of the other Python libraries for interactive figures.
  • Python offers a much broader code ecosystem than R. Pairing this with Shiny will enable some really cool new apps!

Hopefully that gives you sufficient motivation to try Shiny for Python yourself.   If you have any questions or discover cool use cases for Shiny for Python, please reach out.  And as usual, if you have a project in mind or want help developing an interactive figure (or have any other data visualization need), I’d be happy to work with you.  Please click here to submit a consultation request.