Build a BMI Calculator Web App with Python and PyWebIO

πŸ’‘ Problem Formulation: This article provides a comprehensive guide for readers looking to create a web-based Body Mass Index (BMI) calculator. It uses Python, along with the PyWebIO module, to develop a simple, yet functional application. The BMI is calculated by dividing a person’s weight in kilograms by the square of their height in meters. Users input their weight and height, and the application outputs their BMI along with a health classification based on that number.

Method 1: Setting Up PyWebIO

An initial method involves setting up PyWebIO, a Python library that enables the creation of simple web applications directly with Python code, negating the need for knowledge of HTML, JavaScript, or CSS. We’ll establish a basic structure for the web app using PyWebIO, define the input fields for user data, and outline the function for BMI calculation.

Here’s an example:

from pywebio.input import input, FLOAT
from pywebio.output import put_text

def bmi_calculator():
    height = input("Enter your height (in meters):", type=FLOAT)
    weight = input("Enter your weight (in kilograms):", type=FLOAT)
    bmi = weight / (height ** 2)
    put_text(f"Your BMI is: {bmi}")

if __name__ == '__main__':
    import argparse
    from pywebio import start_server
    
    parser = argparse.ArgumentParser()
    parser.add_argument("-p", "--port", type=int, default=8080)
    args = parser.parse_args()
    
    start_server(bmi_calculator, port=args.port)

The output will be a web page with two input boxes for the user to enter their height and weight, followed by a text display of their calculated BMI.

In this snippet, we import necessary modules from PyWebIO and define a bmi_calculator() function that takes user input for height and weight to calculate and display the BMI using put_text(). Finally, we use start_server() to run the web app on a local server.

Method 2: Adding Health Classification

To enhance the calculator, we add a health classification feature, which interprets the BMI score according to standard weight status categories. After calculating the BMI, the application will present the user with information on whether they are underweight, normal weight, overweight, or obese, based on their score.

Here’s an example:

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

def bmi_calculator():
    height = input("Enter your height (in meters):", type=FLOAT)
    weight = input("Enter your weight (in kilograms):", type=FLOAT)
    bmi = weight / (height ** 2)
    
    category = ""
    if bmi < 18.5:
        category = "Underweight"
    elif 18.5 <= bmi < 25:
        category = "Normal weight"
    elif 25 <= bmi < 30:
        category = "Overweight"
    else:
        category = "Obese"
        
    put_text(f"Your BMI is: {bmi} ({category})")

import argparse
from pywebio import start_server

parser = argparse.ArgumentParser()
parser.add_argument("-p", "--port", type=int, default=8080)
args = parser.parse_args()

start_server(bmi_calculator, port=args.port)

The output will similarly display the user’s BMI along with the corresponding health classification.

This code extends the previous example by implementing an if-else structure that matches the calculated BMI to its health classification. This is then presented to the user with put_text(), informing them of their weight status in addition to their BMI score.

Method 3: Styling the App

Though PyWebIO does not require knowledge of HTML or CSS, it does offer options for styling the web app. By using the style() function from the pywebio.output module, we can enhance the visual appeal of our BMI calculator for a better user experience.

Here’s an example:

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

def bmi_calculator():
    with style(put_text("BMI Calculator"), 'color: green; font-size: 20px'):
        height = input("Enter your height (in meters):", type=FLOAT)
        weight = input("Enter your weight (in kilograms):", type=FLOAT)
        
        bmi = weight / (height ** 2)
        put_text(f"Your BMI is: {bmi}")
        
# Remaining code is identical to previous examples

The output will now include styled text for the BMI calculator title.

This snippet demonstrates how the style() function can be called with a put_text() object to apply CSS directly to the output text. In this case, we’ve made the title “BMI Calculator” green and increased its size, which exemplifies a basic way to add a little flair to the web application.

Method 4: Input Validation

It is crucial for a web app to handle user input effectively. PyWebIO provides validators for input functions which ensures that the user data falls within reasonable and safe boundaries. By including input validation in the BMI calculator, we prevent users from entering negative or unrealistically high values.

Here’s an example:

from pywebio.input import *
from pywebio.output import *
from pywebio import start_server

def check_positive(value):
    assert value > 0, 'Value must be positive'

def bmi_calculator():
    height = input("Enter your height (in meters):", type=FLOAT, validate=check_positive)
    weight = input("Enter your weight (in kilograms):", type=FLOAT, validate=check_positive)
    
    bmi = weight / (height ** 2)
    put_text(f"Your BMI is: {bmi}")
    
# Remaining server code is identical to previous examples

The web app will prompt the user again if they enter a value that fails the validation check.

In the provided code, we define a custom validator function check_positive() which uses an assertion to make sure the user input is greater than 0. This function is then passed to the input() functions via the validate parameter to make sure both height and weight are positive numbers.

Bonus One-Liner Method 5: All-In-One Function

For those who prefer minimalistic design or simply want to test functionality quickly, it is possible to condense the creation of the BMI calculator into a single function that handles input, validation, calculations, and output.

Here’s an example:

from pywebio import start_server
from pywebio.input import input, FLOAT, input_group
from pywebio.output import put_text

def bmi_calculator():
    data = input_group("BMI Calculator",[
        input('Enter your height (in meters):', type=FLOAT, validate=lambda h: 'Must be positive' if h <= 0 else None),
        input('Enter your weight (in kilograms):', type=FLOAT, validate=lambda w: 'Must be positive' if w <= 0 else None)
    ])
    
    bmi = data[1] / (data[0] ** 2)
    put_text(f"Your BMI is: {bmi}")
    
start_server(bmi_calculator, port=8080)

The outcome will be a simplified web page with inputs and the calculated BMI.

This consolidated approach uses the input_group() function to gather height and weight details together and includes lambda functions for inline validation. It simplifies the presentation without compromising the core functionality of the app.

Summary/Discussion

  • Method 1: Setting Up PyWebIO. Strengths: Simple setup, minimal coding required. Weaknesses: Features limited by default options.
  • Method 2: Adding Health Classification. Strengths: Provides additional useful information for users. Weaknesses: Slightly more complex code with conditional logic.
  • Method 3: Styling the App. Strengths: Better user experience with enhanced UI. Weaknesses: Requires some knowledge of CSS for advanced styling.
  • Method 4: Input Validation. Strengths: Improved data quality and user error handling. Weaknesses: Extra code for validation logic.
  • Method 5: All-In-One Function. Strengths: Streamlined code, fast deployment. Weaknesses: Potential loss of readability and modularity when extending app features.