Shiny for Python Shinylive: How to Run Shiny for Python Apps Without a Python Server

By:
Dario Radečić
May 14, 2024

Writing Shiny for Python applications is fun and games, but what about deploying them? Well, it's the same story. Shiny for Python Shinylive saves the day by offering a beginner-friendly ways (plural) to share Shiny apps. Today you'll learn a bunch of them. By the end, you'll have your app running on Shinylive through the editor, GitHub, and also deployed locally.

Keep in mind that Shinylive is still an experimental feature, and some features might change in the future. We recommend <a href="https://shiny.posit.co/py/docs/shinylive.html" target="_blank" rel="noopener">following the official Shinylive documentation</a> to stay up to date.

We recently launched a Shiny for Python framework for production-ready applications, Tapyr. Learn more about Tapyr and how you can set it up in this blog post.


Table of contents:
<ul><li><a href="#introduction">Introduction to Shiny for Python Shinylive</a></li><li><a href="#editor">How to Use Shinylive Editor for Sharing Shiny for Python Apps</a></li><li><a href="#github">How to Share Shiny for Python Applications with Shinylive and GitHub</a></li><li><a href="#deploy">Deploy Shiny for Python Apps Anywhere - Experimental</a></li><li><a href="#summary">Summing up Shiny for Python Shinylive</a></li></ul>

<hr />

<h2 id="introduction">Introduction to Shiny for Python Shinylive</h2>
So, what exactly is Shinylive? It's an experimental feature that allows your Shiny for Python applications to run in a web browser. This means you don't need a separate server for running Python.

With Shinylive, Python and Shiny run in the web browser, which stands for both the client and the server of the application.

This was all made possible because of two technologies:
<ul><li><b>WebAssembly</b> - This is a binary format for compiled programs that runs in a web browser at near-native speeds.</li><li><b>Pyodide</b> - A port of Python and many packages compiled into WebAssembly.</li></ul>
The main advantage of a Shinylive deployment is that the computations are done on the client. In many cases, that's beneficial to you as a Shiny developer, since the client browser typically has more power than the server. That's especially the case when you scale the app to dozens or hundreds of concurrent users.

On the other side, you can also consider this to be a disadvantage. For example, sometimes you need to perform intensive computations that require a powerful server. In this case, it's not the best idea to shift the computations to the client.

We'll explore some additional advantages and disadvantages below.
<h3>Pros of Using Shinylive</h3>
Here's a list of clear, no-brainer advantages that come with Shinylive deployment:
<ul><li><b>No installation:</b> You don't need to install Python or Shiny on a computer.</li><li><b>Super easy sharing:</b> Share your applications by generating a shareable URL.</li><li><b>Simple deployment:</b> You can use Shinylive to deploy your apps to any static web hosting service (more on this at the end of the article).</li><li><b>Scalability:</b> Apps are essentially just static files, so it's easy to scale them.</li><li><b>Bullet-proof security:</b> The app isn't running on a server, and hence eliminates almost all security risks.</li></ul>
<h3>Cons of Using Shinylive</h3>
There's a disadvantage for every advantage, and Shinylive is no exception. Let's go over a couple:
<ul><li><b>Python package limitation:</b> Not all Python packages are available on Pyodide. <a href="https://pyodide.org/en/stable/usage/packages-in-pyodide.html" target="_blank" rel="noopener">Here's a list of currently available ones</a>.</li><li><b>Download size:</b> Packages required to run Shiny apps via Python and Pyodide take around 13MB of data. Other packages also have a tool (Numpy = 7.5MB, Pandas = 13MB, Matplolib = 11.5MB). Keep in mind that this data will be cached, so only the first run will be slower.</li><li><b>No secrets:</b> Application data and code are sent to the browser, which means the user can inspect them with ease.</li></ul>
You now know some advantages and drawbacks of using Shinylive. Up next, we'll get practical!

<blockquote>Shiny for Python works wonders with databases - <a href="https://appsilon.com/shiny-for-python-databases-mysql-postgres/" target="_blank" rel="noopener">Here's how to get started with MySQL and Postgres</a>.</blockquote>

<h2 id="editor">How to Use Shinylive Editor for Sharing Shiny for Python Apps</h2>
This section will walk you through using and sharing your Shiny for Python apps via the Shinylive editor.
<h3>Writing the Shiny for Python Application</h3>
First things first - we need an app. We'll leverage the one you've seen in our previous Shiny for Python articles. It essentially plots a histogram of values drawn from a normal distribution. The user can change the number of bins, and the chart updates automatically.

Here's the code for the entire application:
<pre><code class="language-python">from shiny import ui, render, App
import numpy as np
import matplotlib.pyplot as plt
<br>
app_ui = ui.page_fluid(
   # Sidebar layout
   ui.layout_sidebar(
       # Sidebar with the input controls
       ui.panel_sidebar(
           ui.h2("Page Charts"),
           ui.hr(),
           ui.input_slider(id="slider", label="Number of bins:", min=5, max=25, value=15)
       ),
       # Main area with the chart
       ui.panel_main(
           ui.output_plot(id="histogram")
       )
   )
)
<br>def server(input, output, session):
   @output
   @render.plot
   def histogram():
       # 500 samples from a normal distribution centered around 100
       x = 100 + np.random.randn(500)
       plt.title("A histogram", size=20)
       plt.hist(x=x, bins=input.slider(), color="gray", ec="black")
<br>
<br>app = App(ui=app_ui, server=server)</code></pre>
You can paste this code into the <a href="https://shinylive.io/py/editor/" target="_blank" rel="noopener">Shinylive editor</a>. Simply replace the already existing code and hit the run button.

This is what you'll see on the right-hand side:

<img class="size-full wp-image-19536" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d0a363fa53d916efe8_7db9376f_1-1.webp" alt="Image 1 - Shiny for Python editor (1)" width="2952" height="1900" /> Image 1 - Shiny for Python editor (1)

As promised, you can change the number of bins by playing around with the slider in the sidebar:

<img class="size-full wp-image-19538" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d0ebc881cc3834a28a_da880192_2-1.webp" alt="Image 2 - Shiny for Python editor (2)" width="2952" height="1900" /> Image 2 - Shiny for Python editor (2)

And that's our app. Nothing fancy, but it'll do for the rest of the article.
<h3>How to Share Shiny for Python Apps</h3>
Have you noticed the "Share" button in the top right corner of the Shinylive editor? If not, here's what it looks like:

<img class="size-full wp-image-19540" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d14fb9673e4232cf70_458654db_3-1.webp" alt="Image 3 - Creating a shareable link" width="252" height="186" /> Image 3 - Creating a shareable link

Clicking on it will open up a modal window, similar to this one:

<img class="size-full wp-image-19542" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d285b6bd7053b93ac2_09b0379f_4-1.webp" alt="Image 4 - Editor and application URLs" width="1240" height="330" /> Image 4 - Editor and application URLs

This is where all the magic happens. You can share the <b>Editor URL</b>, meaning the user will have access to the code and will be able to change it, or you can share the <b>Application URL</b>, meaning the user will only see the rendered application.

We recommend you click on the "Hide header" checkbox when sharing the application URL, so that the blue <i>Shiny for Python</i> header isn't shown to the user.

You can copy either of these URLs and open them up in a new browser window. Here's what you'll get for the Application URL:

<img class="size-full wp-image-19544" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d26115b77c55a1d182_e7370049_5-1.webp" alt="Image 5 - Shared Shiny for Python application" width="2952" height="1900" /> Image 5 - Shared Shiny for Python application

Impressive, isn't it? Keep in mind that these URLs differ only in one thing - the first one has the <code>/editor/</code> part, while the latter has <code>/app/</code>. You can guess where each one leads to.

Up next, let's explore the option of Shinylive deployment from GitHub.
<h2 id="github">How to Share Shiny for Python Applications with Shinylive and GitHub</h2>
The answer is simple - <b>GitHub gists</b>. We'll now walk you through the process of creating one and using it in Shinylive.

The main advantage of using Gists is that you can change the code at any time, but your sharing URL will stay the same.
<h3>Creating a GitHub Gist</h3>
If you have a GitHub account, you can create a new Gist by clicking on the plus button in the top right corner. Here's how yours should look like once created:

<img class="size-full wp-image-19546" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d3303d514718a29127_5eeef492_6-1.webp" alt="Image 6 - Shiny for Python app GitHub gist" width="1994" height="1888" /> Image 6 - Shiny for Python app GitHub gist

The only thing we've changed is the histogram bar color - from <code>gray</code> to <code>red</code>. It's a non-essential change but will prove to us the GitHub gist connection is actually working.
<h3>Sharing Shiny for Python App Through a GitHub Gist</h3>
Take a look at the gist URL. You only need the ID part, or the part after your username:

<img class="size-full wp-image-19548" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d421d589fe2956bdde_1f5f7bfc_7.webp" alt="Image 7 - GitHub gist URL" width="1048" height="68" /> Image 7 - GitHub gist URL

You can copy this ID part and paste it at the end of the following URL:
<pre>https://shinylive.io/py/app/#gist=</pre>
In our case, the complete URL would be:
<pre>https://shinylive.io/py/app/#gist=6316216a6150963a1553d55cee93b758</pre>
You can now open this URL to verify the connection works:

<img class="size-full wp-image-19550" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d46d93f1ee6ac9aca0_e3440de7_8.webp" alt="Image 8 - Shared Shiny for Python application (2)" width="2056" height="1714" /> Image 8 - Shared Shiny for Python application (2)

And it does - we now have a Shiny for Python application with red histogram bars.

Once again, the main advantage of using gists with Shinylive is that you can update the code and reuse the Shinylive application URL. Feel free to test it out.
<h2 id="deploy">Deploy Shiny for Python Apps Anywhere - Experimental</h2>
Shinylive also allows you to deploy your Shiny for Python applications to static web hosts. This feature is currently experimental, so the details might change in the future. Refer to the <a href="https://appsilon.com/r-shiny-vs-shiny-for-python/" target="_blank" rel="noopener">official documentation</a> if you have any trouble running the code.

This deployment option will essentially allow you to take your app and host it on services such as Netlify or GitHub pages. There's also a Posit Connect option, but these services require an entire article to cover in detail.
<h3>Configuring a Shinylive Local Distribution</h3>
The first step is to install the <code>shinylive</code> Python package. You can do so by running the following command from the Terminal:
<pre><code class="language-bash">pip install shinylive</code></pre>
This is the output you will see:

<img class="size-full wp-image-19552" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d5917cd6e11222c3e3_ec1bf148_9.webp" alt="Image 9 - Installing Shinylive Python package" width="2520" height="1428" /> Image 9 - Installing Shinylive Python package

Once installed, you can create a new Shiny for Python application with the <code>shiny create</code> command. We'll name ours <code>histogram_app</code>
<pre><code class="language-bash">shiny create histogram_app</code></pre>
You should see the following output:

<img class="size-full wp-image-19554" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d654840e14c9c69e8f_de35166b_10.webp" alt="Image 10 - Creating a Shiny for Python app" width="2520" height="1428" /> Image 10 - Creating a Shiny for Python app

And finally, you can now use <code>shinylive</code> to <i>export</i> the Shiny for Python application:
<pre><code class="language-bash">shinylive export histogram_app site</code></pre>
This will create a new <code>site</code> directory with the static app contents:

<img class="size-full wp-image-19556" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d671479ae64929ec71_7aeb4fc9_11.webp" alt="Image 11 - Exporting Shiny for Python app for static serving" width="2520" height="1680" /> Image 11 - Exporting Shiny for Python app for static serving

We have the app exported now, so the only thing left to do is to run it via the web server.
<h3>Serving the Local Application</h3>
Provided your exported Shiny for Python application is stored in a <code>site</code> folder, you can run it by executing the following shell command:
<pre><code class="language-bash">python -m http.server --directory site 8008</code></pre>
If everything went well, you'll see a message that the app is running locally on port 8008:

<img class="size-full wp-image-19558" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d7c6822ae9d748e1e4_4de1ef0e_12.webp" alt="Image 12 - Serving the Shiny for Python app" width="2520" height="1260" /> Image 12 - Serving the Shiny for Python app

You can now open <code>localhost:8008</code> and see your application running locally:

<img class="size-full wp-image-19560" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d7d849b91708eb345fb4_57355f3b_13.webp" alt="Image 13 - Served local Shiny for Python app" width="2952" height="1900" /> Image 13 - Served local Shiny for Python app

You can take things a step further by opening a local Shinylive editor. To do so, just visit <code>localhost:8008/edit</code>, and you'll see a familiar-looking window:

<img class="size-full wp-image-19562" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b019bc7fda7d9cd7dadb2a_14.webp" alt="Image 14 - Local Shinylive editor" width="2308" height="1756" /> Image 14 - Local Shinylive editor

And that's the basic of Shinylive! Let's make a brief recap next.

<hr />

<h2 id="summary">Summing up Shiny for Python Shinylive</h2>
Shinylive makes sharing Shiny for Python apps easier than ever. You can do everything from the online editor, or opt for GitHub gists for more control. Also, you can serve the app locally or on any static site hosting service, such as GitHub pages.

And that's exactly what we'll cover next - taking local Shiny for Python applications online through GitHub pages, Netlify, Cloudflare, and Posit Connect. Make sure to stay tuned to the Appsilon blog to learn more.

<i>What are your thoughts on Shinylive? Does it simplify your workflow for sharing Shiny for Python applications?</i> Let us know in our Shiny community.
<blockquote>Is Shiny for Python better than R Shiny? <a href="https://appsilon.com/r-shiny-vs-shiny-for-python/" target="_blank" rel="noopener">We did the comparison, you do the reading</a>.</blockquote>

Have questions or insights?

Engage with experts, share ideas and take your data journey to the next level!
Explore Possibilities

Share Your Data Goals with Us

From advanced analytics to platform development and pharma consulting, we craft solutions tailored to your needs.

Talk to our Experts
shiny
python
tutorials
shiny for python