Creating Web Applications Using PyWebIO

If you want to build a web application using Python, you can choose to use sophisticated and highly customizable packages such as Flask, FastAPI, or Django; or create a barebones web application using Streamlit. PyWebIO is another Python package that allows you to create simple web applications without prior knowledge of HTML and Javascript. The idea behind PyWebIO is to use the browser as a rich text terminal, which is reflected in the way web applications are written.

What is the difference between Streamlit and PyWebIO?

The key factor that differentiates the two libraries is how the applications are coded and their execution flow. Streamlit works in a reactive way, i.e. every time the user interacts with a widget, the script is re-executed and the output of the widget is updated with the new value returned at runtime . On the other hand, PyWebIO executes code in a linear fashion much like a series of terminal commands. The output functions display content in the browser in real time, and the input function blocks execution until the user submits input, much like Python’s built-in function. input(). This allows developers to easily convert existing terminal programs into web applications by replacing input and output functions.

Let’s review the basic input and output functions of PyWebIO, but first we’ll need to install it.

pip install -U pywebio

Grab

PyWebIO provides a plethora of input functions to retrieve user input through the browser. When an input function is called, a new browser tab appears with an input form. Similar to built-in Python input()the PyWebIO input function is blocking, i.e. it stops the flow of execution until the form is successfully submitted.

 from pywebio.input import *

 meaning = input("What is the meaning of life?") #not the built-in method
 pill_color = select("Which one will you choose", ['Red Pill', 'Blue Pill'], multiple=True)
 device = radio("What device are you using right now?", options=["Laptop", "Desktop", "Smartphone", "Tablet"])
 os = checkbox("What operating system do you prefer for smartphones?", options=["Android", "iOS"]) 

You can learn more about the different input functions here.

To go out

It also provides a wide range of output functions to render all sorts of output in the browser. Refer here to find the list of all available output functions.

 from pywebio.output import *
 from pywebio.input import * 
 import time

 with popup("Subscribe to the page"):
     put_text("I hope you are having a great day!")

 put_markdown('## Welcome to our fruit store')
 put_table([
     ['Fruit', 'Price'],
     ['Blueberry', 20],
     ['Mango', 25], 
     ['Kiwi', 15]
     ])

 fruit = select("Choose your favorite Fruit", ['Blueberry', 'Mango', 'Kiwi'])
 put_text(f"You chose {fruit}. Please wait until it is served!")
 put_processbar('bar')
 for i in range(1, 11):
     set_processbar('bar', i / 10)
     time.sleep(0.05)
 put_markdown(f"Here is your {fruit}! Enjoy!")
 if fruit == 'Mango':
     put_image(open('mango.jpg', 'rb').read())
 elif fruit == 'Blueberry':
     put_image(open('noodle.jpg', 'rb').read())
 else:
     put_image(open('kiwi.jpg', 'rb').read()) 

Create an EDA web application with PyWebIO and Plotly

  1. Import the necessary libraries and classes.
 from pywebio.input import *
 from pywebio.output import put_html, put_loading
 from pywebio import start_server
 import csv 
 import re
 import pandas as pd
 import plotly.express as px 
  1. Create a function that generates a CSV file from a list of lines.
 def list_to_dataframe(file_content):
     with open("data.csv", "w") as csv_file:
         writer = csv.writer(csv_file, delimiter="t")
         for line in file_content:
             writer.writerow(re.split('s+',line))
     return pd.read_csv("data.csv") 
  1. Create the app method and run the PyWebIO server.
 def app():
     file = file_upload(label="Upload CSV file", accept=".csv")
     content = file['content'].decode('utf-8').splitlines()
     df = list_to_dataframe(content)
     columns = list(df.columns)
     target = select("Select target variable", columns)
     columns.remove(target)

     # create a scatter plot for every feature pair
     fig = px.scatter_matrix(df, columns, color=target)
     fig.update_layout(
         width=1200,
         height=1200
     )
     html = fig.to_html(include_plotlyjs="require", full_html=False)
     put_html(html)

     while True:  
         features = select("Select up to three features to plot", options = columns, multiple=True)
         if len(features) == 1:
             fig = px.histogram(df, x=features[0])
             html = fig.to_html(include_plotlyjs="require", full_html=False)
             put_html(html)
         elif len(features) == 2:
             plot_type = radio("What type of plot?", options=["Line", "Scatter", "Bar"])
             if plot_type == "Bar":
                 fig = px.bar(df, x=features[0], y = features[1])
                 html = fig.to_html(include_plotlyjs="require", full_html=False)
                 put_html(html)
             elif plot_type == "Line":
                 fig = px.line(df, x=features[0], y = features[1])
                 html = fig.to_html(include_plotlyjs="require", full_html=False)
                 put_html(html)
             else :
                 fig = px.scatter(df, x=features[0], y = features[1])
                 html = fig.to_html(include_plotlyjs="require", full_html=False)
                 put_html(html)
         else:
             plot_type = radio("What type of plot?", options=["Line", "Scatter"])
             if plot_type == "Scatter":
                 fig = px.scatter_3d(df, x=features[0], y = features[1], z=features[2],
                 color=target)
                 html = fig.to_html(include_plotlyjs="require", full_html=False)
                 put_html(html)
             else:
                 fig = px.line_3d(df, x=features[0], y = features[1], z=features[2])
                 html = fig.to_html(include_plotlyjs="require", full_html=False)
                 put_html(html)
         x = radio("Do you want to continue?", options=["Continue", "Quit"])
         if x == "Quit":
             break

 if __name__=='__main__':
     start_server(app, debug=True) 

Last era

This article introduced PyWebIO, a python library for building web applications that turns your browser into a rich text terminal. It provides input and output functions that make it easy to convert pre-existing terminal scripts into web applications. PyWebIO is compatible with data visualization libraries, such as Plotly, bokeh, etc. and supports asynchronous and coroutine. It can also be integrated into existing web projects created using libraries such as Flask, Django, Tornado.

The references