Make Amazing Data Science Projects using PyScript.js

Aryan Garg 13 Jul, 2022 • 11 min read

This article was published as a part of the Data Science Blogathon.

Introduction on PyScript.js

Source –

What is PyScript.js?

It is a front-end framework that enables the use of Python in the browser. It is developed using Emscripten, Pyodide, WASM, and other modern web technologies.

Using Python in the browser does not mean that it can replace Javascript. But it provides more convenience and flexibility to the Python Developers, especially Machine Learning Engineers.

What PyScript Offers?

1. Programs can communicate between Python and Javascript Objects.
2. It does not require any servers or dedicated hardware for hosting.
3. We can include any required files or packages in the python environment.
4. It supports the use of popular python libraries like Numpy and Pandas.
5. It provides flexibility to the developers. Now they can quickly build their python programs with the existing UI components such as buttons and containers.

This tutorial shows you how we can create our machine learning model with a web GUI using PyScript.

We will use the famous Car Evaluation Dataset to predict the car’s condition based on the six categorical features. We will discuss the dataset later but first, start with setting up the pysscript.js library.

Setting Up PyScript.js

This section will set up our HTML Template and include the pyscript.js library.

We will use VSCode here, but you can choose any IDE.

1. Create a directory named as PyscriptTut.

$ mkdir PyscriptTut
$ cd PyscriptTut

2. Creating an HTML Template

Create an HTML template inside it named index.html

Inside this template, place the starter HTML code

<!doctype html>

<html lang="en">


<!-- Required meta tags -->

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Bootstrap CSS -->

<link rel="stylesheet" href="[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<title>Pyscript Tutuorial</title>


<!-- Optional JavaScript -->

<!-- jQuery first, then Popper.js, then Bootstrap JS -->

<script src="" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

<script src="[email protected]/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>

<script src="[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>



Bootstrap CDN is used for Styling the Web Page

PyScript Installation

We will not install the library on our machine, we will directly import the library from the PyScript website.

Add the below code in the <head> section of your HTML template.

<!-- Pyscript Library -->

<link rel="stylesheet" href="" />

<script defer src=""></script>

Important Note:

You have to use a Local Server to run the HTML Code. Otherwise, you may face issues in importing several libraries in a python environment.

If you try to open the webpage by double-clicking the index.html file (like this file:///home/../…/JavaScript/src/index.js), you may get an error of CORS Policy while importing the libraries, as the ES6 modules are subject to the same-origin policy.

If you are using VSCode, then you can use its Live Server Extension.

Or you can also create a python server writing the below command in the terminal

$ python3 -m http.server

You can access your HTML Page on that URL –

Sample Code

You can try this sample code to check whether PyScript is successfully imported or not.

<!doctype html>
<html lang="en">
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Pyscript Library -->
    <link rel="stylesheet" href="" />
    <script defer src=""></script>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>Pyscript Tutuorial</title>

        print("Welcome to puscript tutorial")
        for i in range(1, 10):

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="[email protected]/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

This is a simple program that prints the number from 1 to 9 using a for-loop.

If everything goes fine, the output looks like that

Hurray 🎉, our PyScript library is installed successfully in our template.

Creating GUI

This section will create a web GUI to use our machine learning model for training and testing.

As mentioned above, we will use Bootstrap Library for creating custom styling. I have also used inline CSS in some places.

1. Add Google Fonts CDN

Add the below code in the <head> section of your HTML template. This will add Montserrat font to our web page.

<!-- Google Fonts CDN -->
<link rel="preconnect" href="">
<link rel="preconnect" href="" crossorigin>
<link href="" rel="stylesheet">

2. Some CSS Configuration

Add the below code to your template. It will enable smooth scrolling on our web page and apply the above font.

    * {
        margin: 0;
        padding: 0;
    html {
        scroll-behavior: smooth;
    body {
        font-family: 'Montserrat', sans-serif;

3. Adding Bootstrap Navbar Component

Add this code in the <body> section to apply a navbar.

<!-- Navbar -->

<nav class="navbar navbar-expand-lg navbar-dark bg-primary">

<a class="navbar-brand" href="#">PyScript Tutorial</a>

<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"

aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">

<span class="navbar-toggler-icon"></span>


<div class="collapse navbar-collapse" id="navbarSupportedContent">

<ul class="navbar-nav mr-auto">

<li class="nav-item active">

<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>


<li class="nav-item active">

<a class="nav-link" href="#trainModel">Train Model <span class="sr-only">(current)</span></a>


<li class="nav-item active">

<a class="nav-link" href="#testModel">Test Model <span class="sr-only">(current)</span></a>





4. Adding Heading Content

We will create a small landing page with some texts and images.

<!-- Heading Content -->
<div style="width: 75%; margin: 20px auto; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 6px 0 rgba(0, 0, 0, 0.12); border-radius: 4px; text-align: center; padding: 10px;">
   <h1>Car Evaluation Dataset</h1>
   <p>A choice to buy or not buy an automobile based on its physical qualifications.</p>
   <img src="images/homeImg.png" style="margin: 20px auto; width: 90%; height: 450px;" class = "img-fluid" alt="">

The Source of the image used in this component can be found here.

5. Component to Train the Model

In this component, we will create some radio buttons and input texts, so that users can select which classifier they want to train and by how many tests split.

<!-- Training Parameters -->
<div style="width: 75%; margin: 30px auto;" id="trainModel">
    <h2>Training of Model</h2>
            <div class="row ml-1">
                <div class="form-check col-lg-6">
                    <input class="form-check-input" type="radio" name="modelSelection" id="rf_model"
                        value="rf" checked>
                    <label class="form-check-label" for="rf_model">
                        Random Forest
                <div class="form-check col-lg-6">
                    <input class="form-check-input" type="radio" name="modelSelection" id="lr_model"
                    <label class="form-check-label" for="lr_model">
                        Logistic Regression
                <div class="form-check col-lg-6">
                    <input class="form-check-input" type="radio" name="modelSelection" id="mlp_model"
                    <label class="form-check-label" for="mlp_model">
                        MLP Classifier
                <div class="form-check col-lg-6">
                    <input class="form-check-input" type="radio" name="modelSelection" id="gb_model"
                    <label class="form-check-label" for="gb_model">
                        Gradient Boosting
            <div class="form-group mt-2">
                <label for="test_split">Choose Test Split</label>
                <input type="number" class="form-control" id="test_split" aria-describedby="testSplitHelp" value="0.25">
                <small id="testSplitHelp" class="form-text text-muted">Answer between 0 to 1.</small>
            <button class="btn btn-primary mt-2" id="trainModelBtn" type="button">Train Model</button>

6. Component for Alert Messages

This component is used for alerts and success messages.

<!-- Heading Bar -->
<div style="width: 75%; margin: 10px auto; background-color: #0275d8; border-radius: 3px; text-align: center;">
    <p style="color: white; font-size: 1.3rem; font-weight: 600;" id="headingText"></p>

7. Component for checking the Training Results

In this, we can see the Accuracy and Weighted F1 Score of the selected model after training.

<!-- Training Summary -->
<div style="width: 75%; margin: 20px auto; border: 1px solid rgb(211, 211, 211); border-radius: 3px; padding: 10px;">
    <h2>Training Summary</h2>
    <div style="display: flex;">
         <p style="flex-grow: 1;">Selected Model: </p>
         <p id="selectedModelContentBox">Not available</p>
     <div style="display: flex;">
          <p style="flex-grow: 1;">Test Split: </p>
          <p id="testSplitContentBox">Not available</p>
     <div style="display: flex;">
          <p style="flex-grow: 1;">Accuracy Score: </p>
          <p id="accuracyContentBox">Not available</p>
      <div style="display: flex;">
           <p style="flex-grow: 1;">Weighted F1 Score: </p>
           <p id="f1ContentBox">Not available</p>

8. Component for selecting Car Parameters

We can select the six parameters to check the performance of the car.

<!-- Car Parameters -->
<div id="testModel" style="width: 75%; margin: 20px auto;">
    <h2>Car Parameters</h2>
        <div class="row">
            <div class="col-lg-4">
                <div class="form-group">
                    <label for="buying_price">Buying Price</label>
                    <select class="form-control" id="buying_price">
                        <option value="3">Very High (above 15lakh)</option>
                        <option value="2">High (around 10lakh)</option>
                        <option value="1">Meduim (around 7.5lakh)</option>
                        <option value="0">Low (below 5lakh)</option>
            <div class="col-lg-4">
                <div class="form-group">
                    <label for="maintanence_price">Maintanence Price</label>
                    <select class="form-control" id="maintanence_price">
                        <option value="3">Very High (2-3 LPA or above)</option>
                        <option value="2">High(around 1.5 LPA)</option>
                        <option value="1">Meduim(around 1 LPA)</option>
                        <option value="0">Low(below 50k per annum)</option>
            <div class="col-lg-4">
                <div class="form-group">
                    <label for="doors">No. of doors</label>
                    <select class="form-control" id="doors">
                        <option value="0">2</option>
                        <option value="1">3</option>
                        <option value="2">4</option>
                        <option value="3">>=5</option>
        <div class="row">

            <div class="col-lg-4">
                <div class="form-group">
                    <label for="persons">No. of Persons</label>
                    <select class="form-control" id="persons">
                        <option value="0">2</option>
                        <option value="1">4</option>
                        <option value="2">greater than 6</option>
            <div class="col-lg-4">
                <div class="form-group">
                    <label for="luggage">Luggage Space</label>
                    <select class="form-control" id="luggage">
                        <option value="2">High (around 450 litres) </option>
                        <option value="1">Medium (around 250 litres)</option>
                        <option value="0">Low (below 150 litres)</option>
            <div class="col-lg-4">
                <div class="form-group">
                    <label for="safety">Safety</label>
                    <select class="form-control" id="safety">
                        <option value="0">No Air Bags</option>
                        <option value="1">Front Air Bags</option>
                        <option value="2">Front & Back Air Bags</option>
        <button class="btn btn-primary disabled" id="submitBtn" type="button" disabled>Submit</button>

The Submit will remain disabled until you train the model.

9. Component to Output the Result

This component displays the predicted value.

<!-- Output Bar -->
<div style="width: 75%; margin: 10px auto; background-color: #5cb85c; border-radius: 3px; text-align: center;">
    <p style="color: white; font-size: 1.3rem; font-weight: 600;" id="resultText"></p>

10. Footer (Optional)

This is the footer for our web page

<footer style="background-color: #0275d8; bottom: 0; left: 0; text-align: center; color: white; padding: 3px;">
     <p style="margin: 0;">Made with &#10084; using PyScript.js</p>

Our GUI is now created, ✌

Small Note

From now onwards, we will train our machine learning model. We need to add libraries in the Python Environment

Add the below code in the <head> tag of the HTML Template to import all the required non-standard libraries.

    - pandas
    - scikit-learn
    - numpy

Create a <py-script> </py-script> tag inside the <body> tag of the HTML Template. We will write all the python codes inside that py-script tag.

Importing Libraries

Firstly we will import all the necessary libraries

import pandas as pd

import pickle

from sklearn.model_selection import train_test_split, GridSearchCV

from sklearn.linear_model import LogisticRegression

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier

from sklearn.neural_network import MLPClassifier

from sklearn.metrics import accuracy_score, f1_score

from pyodide.http import open_url

import numpy as np

Dataset Preprocessing

As discussed earlier, we will use Car Evaluation Dataset from UCI ML Repository.

You can download the dataset from that link.

This dataset contains six categorical features, which are Buying Price, Maintenance Price, No. of Doors, No. of Persons, Luggage Capacity, and Safety Qualifications

1. Buying Price – low, mid, high, high
2. Maintenance Price – low, mid, high, high
3. No. of Doors – 2, 3, 4, more
4. No. of Persons – 2, 4, more
5. Luggage – small, med, big
6. Safety – low, mid, high

The Output is classified into four classes namely, unacc, acc, good, vgood

These are as follows:
1. unacc – Unaccepted
2. acc – Accepted
3. good – Good
4. vgood – Very Good

Function to Upsample the Dataset

def upSampling(data):
    from sklearn.utils import resample
    # Majority Class Dataframe
    df_majority = data[(data['score']==0)] 
    samples_in_majority = data[data.score == 0].shape[0]
    # Minority Class Dataframe of all the three labels
    df_minority_1 = data[(data['score']==1)]
    df_minority_2 = data[(data['score']==2)]
    df_minority_3 = data[(data['score']==3)]
    # upsample minority classes
    df_minority_upsampled_1 = resample(df_minority_1, 
                                    n_samples= samples_in_majority, 
    df_minority_upsampled_2 = resample(df_minority_2, 
                                    n_samples= samples_in_majority, 
    df_minority_upsampled_3 = resample(df_minority_3, 
                                    n_samples= samples_in_majority, 
    # Combine majority class with upsampled minority classes
    df_upsampled = pd.concat([df_minority_upsampled_1, df_minority_upsampled_2, df_minority_upsampled_3, df_majority])

    return df_upsampled

Function to read input data and return processed data.

def datasetPreProcessing():
    # Reading the content of CSV file.
    csv_url_content = open_url("")
    data = pd.read_csv(csv_url_content)

    pyscript.write("headingText", "Pre-Processing the Dataset...") # This is used to send messages to the HTML DOM.

    # Removing all the null values

    # Removing all the duplicates

    coloumns = ['buying', 'maint', 'doors', 'people', 'luggaage', 'safety', 'score']

    # Converting Categorical Data into Numerical Data
    data['buying'] = data['buying'].replace('low', 0)
    data['buying'] = data['buying'].replace('med', 1)
    data['buying'] = data['buying'].replace('high', 2)
    data['buying'] = data['buying'].replace('vhigh', 3)

    data['maint'] = data['maint'].replace('low', 0)
    data['maint'] = data['maint'].replace('med', 1)
    data['maint'] = data['maint'].replace('high', 2)
    data['maint'] = data['maint'].replace('vhigh', 3)

    data['doors'] = data['doors'].replace('2', 0)
    data['doors'] = data['doors'].replace('3', 1)
    data['doors'] = data['doors'].replace('4', 2)
    data['doors'] = data['doors'].replace('5more', 3)

    data['people'] = data['people'].replace('2', 0)
    data['people'] = data['people'].replace('4', 1)
    data['people'] = data['people'].replace('more', 2)

    data['luggaage'] = data['luggaage'].replace('small', 0)
    data['luggaage'] = data['luggaage'].replace('med', 1)
    data['luggaage'] = data['luggaage'].replace('big', 2)

    data['safety'] = data['safety'].replace('low', 0)
    data['safety'] = data['safety'].replace('med', 1)
    data['safety'] = data['safety'].replace('high', 2)

    data['score'] = data['score'].replace('unacc', 0)
    data['score'] = data['score'].replace('acc', 1)
    data['score'] = data['score'].replace('good', 2)
    data['score'] = data['score'].replace('vgood', 3)

    upsampled_data = upSampling(data)

    return upsampled_data

Let’s understand these above functions in more detail:

1. Firstly, we have read the CSV File using the Pandas library.

2. You may be confused by this line py script.write(“headingText”, “Pre-Processing the Dataset…”).

This code updates the messages component in the HTML DOM that we have created above.

You can write any message in any HTML Tag

py script.write(<component_id>, <your_message>)

3. Then, we have removed the null values and the duplicates. But luckily, this dataset does not contain any null values.

4. Further, we have converted all the categorical data into numerical data.

5. Finally, we have performed upsampling of the dataset.

You can observe that the number of samples in one particular class is far more than in the other classes. Our model will be biased towards a specific class because it has very little data to train on other classes.

So we have to increase the number of samples in other classes. It is also called Upsampling.

I have created a separate function named upSampling that will upsample the data.

Now we have an equal number of samples for all the classes.

Training the Model

Function to check which machine learning model is selected by the user for training.

def model_selection():
    selectedModel = document.querySelector('input[name="modelSelection"]:checked').value;
    if selectedModel == "rf":
        document.getElementById("selectedModelContentBox").innerText = "Random Forest Classifier";
        return RandomForestClassifier(n_estimators=100)
    elif selectedModel == "lr":
        document.getElementById("selectedModelContentBox").innerText = "Logistic Regression";
        return LogisticRegression()
    elif selectedModel == "gb":
        document.getElementById("selectedModelContentBox").innerText = "Gradient Boosting Classifier";
        return GradientBoostingClassifier(n_estimators=100, learning_rate=1.0, max_depth=1, random_state=0)
        document.getElementById("selectedModelContentBox").innerText = "MLP Classifier";
        return MLPClassifier()

Function to train the model on the chosen classifier.

def classifier(model, X_train, X_test, y_train, y_test):
    clf = model, y_train)
    y_pred = clf.predict(X_test)
    y_score =, y_train)
    acc_score = accuracy_score(y_test, y_pred)
    f1Score = f1_score(y_test, y_pred, average='weighted')
    return acc_score, model, f1Score

The below function triggers when the user clicks the train button.

def trainModel(e=None):
    global trained_model
    processed_data = datasetPreProcessing()
    # Take the Test Split as an input by the user
    test_split = float(document.getElementById("test_split").value)
    # If the test split is greater than 1 or less than 0 then we will throw an error.
    if test_split > 1 or test_split < 0:
        pyscript.write("headingText", "Choose Test Split between 0 to 1")
    document.getElementById("testSplitContentBox").innerText = test_split;

    X = processed_data[['buying', 'maint', 'doors', 'people', 'luggaage', 'safety']]
    y = processed_data['score']
    # Splitting the Dataset into training and testing.
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_split, random_state=42)
    # Below function can return the classification model choosen by the user
    model = model_selection()
    pyscript.write("headingText", "Model Training Started...")
    acc_score, trained_model, f1Score = classifier(model, X_train, X_test, y_train, y_test)
    pyscript.write("headingText", "Model Training Completed.")
    # Writing the value of accuracy and f1-score to the DOM
    document.getElementById("accuracyContentBox").innerText = f"{round(acc_score*100, 2)}%";
    document.getElementById("f1ContentBox").innerText = f"{round(f1Score*100, 2)}%";

    # Below code is to enable the Model Training Button when the Model is successfully trained.
    document.getElementById("submitBtn").disabled = False;
    document.getElementById("trainModelBtn").disabled = False;

    if e:
    return False

The above codes are self-explanatory, and I have also added some comments to the code.

Testing the Model

In this section, we will test our model on the six parameters that we have discussed above.

Below is the function to test the model.

def testModel(e=None):
    buying_price = int(document.getElementById("buying_price").value)
    maintanence_price = int(document.getElementById("maintanence_price").value)
    doors = int(document.getElementById("doors").value)
    persons = int(document.getElementById("persons").value)
    luggage = int(document.getElementById("luggage").value)
    safety = int(document.getElementById("safety").value)

    arr = np.array([buying_price, maintanence_price, doors, persons, luggage, safety]).astype('float32')
    arr = np.expand_dims(arr, axis=0)
    result = trained_model.predict(arr)
    condition = ""
    if result[0] == 0:
        condition = "Unaccepted"
    elif result[0] == 1:
        condition = "Accepted"
    elif result[0] == 2:
        condition = "Good"
        condition = "Very Good"

    pyscript.write("resultText", f"Predicted Value: {condition}")

    if e:
    return False

Firstly, we will take the input from the user and the feed that input to the model for prediction. Then finally, we output the results.

Our machine learning model is now trained.

Finally, add the below code to trigger the Python functions by clicking the HTML Buttons.

document.getElementById("submitBtn").onclick = testModel
document.getElementById("trainModelBtn").onclick = trainModel


GitHub Code – Link
Deployed Version – Link

Before PyScript, we don’t have any proper tool to use Python on the client-side. Frameworks such as Django or Flask can mainly use Python on the backend. In recent years, Python has grown its population immensely. It has been used in Machine Learning, Artificial Intelligence, Robotics, etc.

In this article, we have trained and tested a machine learning model completely in HTML language. You can increase the model’s accuracy by tuning some hyperparameters or searching for the best parameters using Grid Search CV or Randomized Search CV.

The main focus of this article is to use the PyScript.js library, not to achieve a high accuracy classification model.

The key takeaways of this tutorial are:
1. Firstly, we have imported the pyscript.js library in the HTML template and run a basic python code.
2. We have created all the required components in the HTML DOM.
3. Further, we have performed dataset pre-processing and trained the model according to user selection.
4. Finally, we have written the code to test the model based on the user’s input.

It is all for today. I hope you have enjoyed the article. If you have any doubts or suggestions, feel free to comment below. Or you can also connect with me on LinkedIn. I will be delighted to get associated with you.

Do check my other articles also.

Thanks for reading, 😊

GitHub | Instagram | Facebook

The media shown in this article is not owned by Analytics Vidhya and is used at the Author’s discretion.

Aryan Garg 13 Jul 2022

Frequently Asked Questions

Lorem ipsum dolor sit amet, consectetur adipiscing elit,

Responses From Readers


Related Courses