Stanley Ulili I'm a freelance web developer and researcher from Malawi. I love learning new things, and writing helps me understand and solidify concepts. I hope by sharing my experience, others can learn something from them.

Intro to PyScript: Run Python in the browser

21 min read 5984

Intro to PyScript: Run Python in the browser

For a long time, JavaScript has been the dominant language in frontend development due to its ability to run natively in the browser and interact with HTML and CSS through the DOM API. With the advent of WebAssembly, things have started to change slowly. Languages such as Go, Rust, C, C++, and many others can now run in the browser at near-native speeds, and Python hasn’t been left behind.

With the introduction of PyScript, frontend developers can now build rich frontends with Python. Furthermore, they can also tap into the Python ecosystem, which has useful scientific modules such as NumPy, Matplotlib, and many more.

In this tutorial, we’ll cover the following:

Prerequisites

To get the most of this tutorial, you’ll need:

  • A basic understanding of HTML, CSS, and JavaScript
  • Familiarity with Python syntax
  • A web server. We will create a simple server using Python, so make sure you have Python installed on your system
  • A web browser; PyScript documentation currently recommends Chrome

What is PyScript?

PyScript is an open source web framework that allows you to create frontend web applications using Python. With PyScript, you can either embed Python code in HTML, or link to a Python file and the code will execute in the browser — without running Python in the backend.

PyScript was created by Anaconda and was publicly announced on April 30 at PyCon US 2022. At the time of writing, PyScript is in an alpha state and is actively being developed, so breaking changes and newer features are to be expected since it hasn’t been stably released yet.

How does PyScript work?

PyScript builds upon Pyodide, which ports CPython to WebAssembly. WebAssembly is a low-level binary format that allows you to write programs in other languages, which are then executed in the browser. With CPython in WebAssembly, we can install and run Python packages in the browser, while PyScript abstracts most of the Pyodide operations, allowing you to focus on building frontend apps with Python in the browser.

Setting up your project folder for PyScript

Before we start using PyScript, let’s create the directory where our code will reside.

To do that, open your terminal and create the project directory using the mkdir command in the location of your choosing:

mkdir pyscript_demo

Next, move into the directory you just created using the cd command:

cd pyscript_demo

Disabling auto-formatting tools like Prettier

Often, frontend developers use auto-formatting tools like Prettier in their text editors to format code on save. While this works well for HTML, CSS, and JavaScript, this can cause issues in Python code because Python is strict about indentation.

Currently, auto-formatting tools like Prettier don’t recognize PyScript syntax, which is just about two months old as of this writing. These tools auto-format Python code like JavaScript, which breaks the code indentation. To remedy this, we’ll disable auto-formatting for this directory for now.

Assuming you’re using VSCode, we can disable auto-formatting as follows.

In your project directory, create a .vscode directory and navigate into the directory with the following command.

mkdir .vscode && cd .vscode

Next, create a settings.json file and add the following contents:

{
  "editor.formatOnSave": false
}

With that, the auto-format on save feature for this directory has been disabled in VSCode and we are now ready to start using PyScript.

Getting started

Now that our directory is set up for PyScript, we will first add links to the PyScript assets comprising of a CSS file and JavaScript file in the <head> section of an HTML page.

Once the assets have been added, you can use PyScript in an HTML file in either of two ways:

  • Internal PyScript: You can write and place your Python code within the <py-script> tag in an HTML file. The <py-script> tag can be added in the <head> or <body> tag depending on your task at hand
  • External PyScript: This is where you write your Python code in a file ending with .py extension, which you can then reference in the <py-script> tag using the src attribute

Internal PyScript

The easiest and fastest way to start using PyScript is to embed Python code in the HTML file. Let’s do that!

Open your preferred text editor, create the hello-world.html file and add the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Hello World!</title>
    <!-- linking to PyScript assets -->
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <!-- Put Python code inside the the <py-script> tag -->
    <py-script>print("Hello World!")</py-script>
  </body>
</html>

In the <head> section, we link to the pyscript.css file, which contains styles for PyScript visual components, REPL, the PyScript loader, etc. After that, we link to the pyscript.js file, which sets up the necessary features for using PyScript, such as creating tags like <py-script> where you can write your Python code.



In the <body> tag, you embed Python code in the <py-script> tag. We are keeping things simple for now, so we just print Hello World to the user.

Make sure to save your file in the root of your project directory and open the hello-world.html file in Chrome. It will take a couple of seconds to load, and once the page has been loaded, it will look similar to this:

Browser prints "Hello, World!"

External PyScript

While putting Python code in the <py-script> tag works, a much better and more scalable approach is to add the code in an external file and reference it in the HTML file as you create more HTML pages or your scripts get larger.

The following are some of the reasons why you should consider using PyScript code in an external file:

  • The file can be cached by the browser, leading to faster performance
  • You can reference the file in multiple pages, reducing duplication
  • Your Python code can be formatted with tools like black or Python linters. These tools don’t currently work on Python code embedded in an HTML file

To use PyScript externally, we will create an index.html file, a Python file ending with .py extension containing our Python code, and finally reference the Python file in the index.html file.

Creating the index.html file

Create an index.html file and link to the PyScript assets:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Greetings!</title>
    <!-- linking to PyScript assets -->
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  </body>
</html>

The file isn’t doing much; we are just linking to the PyScript resources. To make it more useful, we will create a main.py file where our Python code will reside.

Creating the main.py file

Let’s create a Python function that prints a greeting message.

In your text editor, create the main.py file and add the code below:

def greetings(name):
    print(f'Hi, {name}')

greetings('John Doe')

The greetings() function takes a name parameter and prints a greeting message with the name stored in the name parameter. When we call the greetings() function with John Doe as an argument, it prints hi, John Doe.

Linking the main.py file in the HTML file

Now that you’ve created the Python code, you’ll reference the main.py file in the index.html file.


More great articles from LogRocket:


Open the index.html and add the line inside the <body> tag:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Greetings!</title>
   <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  // add the following line
  <py-script src="./main.py"></py-script>
  </body>
</html>

The <py-script> tag has a src tag, which accepts file path of the Python file.

Opening the index.html file in the browser

Now that everything is in place, we will open the index.html in the browser.

However, browsers will refuse to load and execute the external Python file due to the Cross-Origin Resource Sharing (CORS) policy error. To solve this, we will need to use a server. Good thing Python ships with a web server that we can use! The server doesn’t need to be created by Python, you can use live-server or any server of your choosing.

To create a server, open the terminal in the root directory of your project and run the following command:

python -m http.server

Next, open Chrome and visit http://0.0.0.0:8000/. The server will automatically load the index.html file and you will see the following:

The browser prints our greeting

For the rest of this tutorial, we will be referencing an external Python file, which will require us to use a server to avoid CORS errors, and sometimes we will embed Python code in HTML for brevity sake.

Using the PyScript REPL

PyScript comes with a Read-Eval-Print Loop (REPL), which you can use to experiment and try out Python code.

To use the REPL, add the <py-repl> tag in the <body> tag in your index.html file:

<!DOCTYPE html>
  ...
  <body>
  <py-script src="./main.py"></py-script>
  // add the following tag
  <py-repl></py-repl>
  </body>
</html>

With the server still running, visit http://0.0.0.0:8000/. You will see a new section where you can enter Python code.

You can import modules, evaluate expressions, create functions, and do many more things. To see what an expression evaluates to, you need to click the green Play icon.

The following picture shows some of the operations you can do:

The PyScript REPL in the browser

Now that we now know how to use a REPL, next we will learn how to create and use modules in PyScript.

Using Python modules in PyScript

In this section, we will create a custom Python module and use it in our code. We will also use modules from the Python standard library, as well as third-party modules.

To use modules, we will introduce a new tag, <py-env>, which allows us to reference modules or module file paths.

Creating custom modules

Let’s create a local module containing two functions.

Create a mathslib.py file in your project directory and add the code below:

def add(num1, num2):
    return num1 + num2

def subtract(num1, num2):
    return num1 - num2

Here we created two functions that do addition and subtraction operations.

Next, create a modules.html file and add the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>local modules</title>
    <!-- linking to PyScript assets -->
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
 <py-env>
    - paths:
        - mathslib.py
  </py-env> 
  <py-script>
from mathslib import subtract
print(subtract(8, 4))
  <py-script>
  </body>
</html>

In the <body> tag, we use the <py-env> tag, which accepts a YAML list that has paths as its key. The mathslib.py is the file path of the custom module relative to the modules.html file. Once the path to the custom module is specified, PyScript will import the module in the file.

With the module loaded, in the <py-script> tag, we import the subtract() function from mathslib.py and invoke the function with the arguments 8 and 4.

With the server running, visit http://0.0.0.0:8000/modules.html and you will see a page similar to this:

The result of our subtraction function

Importing modules from the Python standard library

PyScript, with the help of Pyodide, provides access to a lot of modules available in the Python standard library that are ready for you to use, with the exception of the following:

  • tkinter
  • venv
  • dbm

Visit the Pyodide documentation to see a comprehensive list. Also, take note of the modules that are included but not functional, such as the multiprocessing, threading, and sockets modules.

The modules in the standard library are available in the PyScript namespace by default; you only need to import them to use them in the file.

Still in the modules.html file, modify the Python code in the <py-script> tag to generate a random number using the random module:

from mathslib import subtract
import random
print(subtract(8, 4))
print("random number generated: ")
print(random.randint(1, 12))

Now visit the http://0.0.0.0:8000/modules.html page and you will see a random number generated each time you refresh the page:

The result of our subtraction function and our randomly generated number

Using third-party packages

Apart from using inbuilt Python modules, you can also use third-party libraries shipped in Pyodide, such as:

For a full list of supported third-party packages, visit the Pyodide documentation or keep a close eye on the Pyodide GitHub repo.

To add a third-party package, create a new HTML file, third-party.html, and add the following code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>local modules</title>
    <!-- linking to PyScript assets -->
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <!-- thirdparty dependencies added here -->
 <py-env>
    - numpy 
    - matplotlib
  </py-env> 
  <py-script>
import numpy as np
import matplotlib.pyplot as plt
arr = np.array([1, 2, 3, 4, 5])
plt.plot(arr)
plt
  <py-script>
  </body>
</html>

In the <py-env> tag, we add a list of third-party packages we want to use in our project, which are the NumPy and Matplotlib packages. Next, in the <py-script> tag, we import NumPy as np and Matplotlib as plt. Following this, we call NumPy’s array method, which creates an array that is then stored in the arr variable. After that, we call the Matplotlib’s plot method with the array arr as an argument to plot a graph.

Make sure your file is saved and visit the http://0.0.0.0:8000/third-party.html page. You should see a graph similar to the following:

Our example line graph

Now that you understand how to use custom, inbuilt modules and third-party packages, we will learn how to access and manipulate HTML elements in the next section.

Accessing and manipulating HTML elements using PyScript

In this section, we will learn how to select an HTML element using an ID or a CSS class, modify an element, attach events to an element, and create new elements using PyScript.

Using the Element class

PyScript ships with the Element class, which allows you to select an HTML element using its ID.

To see how it works, create an elements.html file and insert the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Element class</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <ul id="navigation">
    <li class="home">home</li>
    <li class="about">about</li>
    <li class="services">services</li>
    <li class="contact">contact</li></ul>
  </div>
  <div id="output"></div>
  <py-script src="./access-elements.py"></py-script>
  </body>
</html>

In the <body> tag, we have a <ul> element with an ID of navigation. We will use the ID to select this element using the Element class. The selected instance will give us methods that we can use to select the descendants and manipulate them.

Another tag we will use is the <div> with an ID of output. We will modify its innerHTML to write a new value. Finally, after the <div> tag, we link to the access-elements.py file that will contain our Python code. It doesn’t exist yet, so let’s go ahead and create it.

Once you create the access-elements.py file, add the following code to it:

ul_element = Element("navigation")
first_element = ul_element.select('.home').add_class('first')
second_element = ul_element.select('.about').remove_class('about')
div_element = Element("output")
div_element.write("Value set from PyScript")

In the preceding code, we use the Element class to access the <ul> element using the navigation ID.

When an element is selected using the Element class, you can take advantage of some of the following methods:

  • write(): Sets the innerHTML value
  • select(): Uses a CSS selector to find descendant elements
  • add_class(): Adds one or more classes to an element
  • remove_class(): Removes one or more classes from an element

In the second line, we use the select() method to select the first child element of the <ul> element using its class name, home. After selecting the child, we call the add_class() method to add a new class first to the <li> element.

In the third line, we access the second child element by its class name, about, and then remove its class about using the remove_class() method.

Next, we call the Element class with the ID output, which provides a reference to the <div> element that resides after the ul element in the elements.html file. Finally, we call the write() method with the string Value set from PyScript. The method will set <div> element innerHTML value to the string argument.

With the server still up, visit http://0.0.0.0:8000/elements.html and inspect the <ul> element. You will see the first <li> element now has an extra class (first), the second element has no class, and the div element now has the text we set in Python.

Our <ul> element when inspected

Attaching events to elements

We can now select HTML elements and do some basic manipulations. In this section, we will attach a click event to an element and have Python code execute when the element has been clicked.

Create an events.html file and write the code below:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Adding Events</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <button id="click-btn" class="bg-blue-500 text-white" pys-onClick="handle_click">Click</button>
  <div id="output"></div>
  <py-script src="./event-handlers.py"></py-script>
  </body>
</html>

In the <body> tag, we have a <button> with a class attribute containing some classes that are part of the pyscript.css file. The <button> tag also has a pys-onclick attribute, which attaches a click event to the button. The pys-onclick attribute accepts the function name handle_click, which will be the function that runs when the button is clicked.

Next, we have the div element with an ID of output. We will modify the element in innerHTML with the handle_click function we define.

Finally, we link to the event-handlers.py file, which will contain the event handler function.

Let’s define the event-handlers.py and add the following:

def handle_click(e):
    pyscript.write("output", "you clicked the button")

The handle_click function has a parameter, e, which is an event object passed automatically to the function when you click the button. Inside the function, we invoke the PyScript’s write() method, which takes two arguments: the element ID output and the value we want to write, in our case, you clicked the button.

Make sure your server is running:

python -m http.server

Then visit the URL http://0.0.0.0:8000/events.html in Chrome. When the page loads, click the button, and a message reading “you clicked the button” will appear:

The output after we click the button

Using JavaScript to access and manipulate the DOM

PyScript ships with a js module that gives you access to JavaScript methods, like querySelector(), createElement(), appendChild(), etc., to access and manipulate HTML elements. With these, you’ll be able to mix JavaScript and Python to do some cool DOM manipulation. Here is an example:

import js

print(js.window.innerHeight)

nav = js.document.createElement("div")
js.document.body.prepend(nav)

js.console.log("nav element created")

As you can see, we are mixing Python code methods like print() together with JavaScript window or document properties.

In this section, we will mostly focus on document methods, and conveniently, PyScript makes it available in the Python scope automatically. We won’t even need to import the js module to use the document methods.

Create a dom.html file and add the following code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Mixing JavaScript and Python</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <ul id="navigation">
  </ul>
  <py-script src="./js-dom.py"></py-script>
  </body>
</html>

In the <body> tag, we only have an empty <ul> element with an ID of navigation. Next, we reference the js-dom.py that will contain our Python code.

Create the js-dom.py file and add the following contents:

nav_parent = document.querySelector('#navigation')
nav_texts = ["home", "about", "services", "contact"]
for text in nav_texts:
    nav_item = document.createElement("li")
    nav_item.textContent = text
    nav_item.className = "nav_element"
    nav_parent.appendChild(nav_item)

In the first line, we call the querySelector() method of the document module with #navigation as its argument. The method will find and return an element with an ID of navigation, which is the <ul> element in the dom.html file.

In the second line, we create a list of navigation text and store it in the nav_texts variable. After that, we iterate over the nav_texts list. On each iteration, we invoke the createElement() method with a string li to create an <li> element.

Following this, we add text to the <li> element using the textContent property, and add a class name nav_element to the <li> element using the className property. Finally, we append the <li> element to the <ul> element by calling the appendChild() with the nav_item element as the argument.

Make sure your file is saved and the server is still running. Visit http://0.0.0.0:8000/dom.html, and you will see a page that resembles the following:

A list of navigation texts

If you dig further and inspect the elements, you will see that the <li> elements have been created with the class name nav_element, which we set in Python:

List items with the `nav_element` class

We can now access and manipulate the DOM using the Element class, attach events to elements, and use JavaScript to query and modify the DOM. Next, we will fetch data from an API using PyScript.

Fetching and rendering data from an API

In this section, we will use PyScript to send a GET request to an API to retrieve data. The API we will use is the Random Data API. We will create a button with a click event that runs a function that calls the API every time the button is clicked.

Create a fetch_data.html file in your directory and add the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Fetch data from API</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <button id="get-name" class="bg-green-600 text-white" pys-onClick="get_random_name">Generate Random Name</button>
  <div id="output"></div>
  <py-script src="./fetch.py"></py-script>
  </body>
</html>

The code should be familiar at this point. The most important part is the <button> tag, which has the pys-onClick attribute that accepts the get_random_name() function. The function will reside in the fetch.py file linked at the bottom. Let’s go ahead and create the file.

In your text editor, create a new file named fetch.py with the following contents:

from pyodide.http import pyfetch
import asyncio

async def get_random_name(e): 
    response = await pyfetch(url="https://random-data-api.com/api/name/random_name", method="GET")
    data = await response.json()
    first_name = data.get('first_name')
    middle_name = data.get('middle_name')
    last_name = data.get('last_name') 
    output =  f"Random name: {first_name} {middle_name} {last_name}"
    pyscript.write('output', output)

In the first line, we import the pyfetch() method from the pyodide.http module, which allows us to make asynchronous network requests. In the second line, we import the asyncio module, which is part of the Python standard library and provides the async and await keywords that are useful for creating asynchronous functions.

Next, we define an asynchronous function get_random_name() by prefixing it with the async keyword from the asyncio module. Within the function, we invoke the pyfetch() method that accepts two arguments:

  • URL: The API endpoint
  • method: Species the HTTP method you want to use, which is the GET method here.

When pyfetch() runs, it returns an object, which is then stored in the response variable. In the line that follows, we call the json() on the response object to parse the JSON and return a Python dictionary, which is then stored in the data variable.

In the next few lines, you extract the first name, middle name, and last name from the data dict and store them in their respective variables. Finally, we concatenate the names using Python’s f-strings and invoke the pyscript.write() method to write the data in the <div> element with an ID of output.

Make sure your server is running and visit the http://0.0.0.0:8000/fetch_data.html page. Once the page loads, click the Generate Random Name button. You will see that a new name is generated each time the button is clicked:

The random name from the Random Name API

Persisting data using localStorage

In this section, we will use local storage to save and retrieve data. Local storage is an object in the web browser that can store data without an expiration date. Python can use local storage by importing it from the js module.

To use local storage, we will create a text area that allows users to type in comments. If they want to save the comment, they will click a save button that will run a function that saves the data in local storage. Every time the page is visited, the data will be retrieved from local storage and the text area will be set to the data.

Create a storage.html file and add the following contents:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Store data in local storage</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
  <textarea id="comment" class="block border"></textarea>
  <button id="save" class="bg-green-600 text-white"
   pys-onClick="save_comment">Save</button>
  <py-script src="./local-storage.py"></py-script>
  </body>
</html>

In the <body> tag, we create a <textarea> tag with an ID comment. We will use this ID to get a reference of the text area element in Python. Next, we have a button that has save as its ID and a click event that will invoke the function save_comment, which we haven’t defined yet. Finally, we reference the local-storage.py, which will contain our Python code. Let’s create the file now.

Create local-storage.py and add the following:

from js import localStorage

def save_comment(e):
    text =  Element("comment").value
    localStorage.setItem("comment", text)

if localStorage.getItem("comment"):
    text_area =  Element("comment")
    text_area.write(localStorage.getItem("comment"))

First, we import the localStorage object from the js module. Next, we define the save_comment() function, which takes e as the parameter. Inside the function, we invoke the Element class with the ID comment to get a reference of text area. Once the method finds the text area, we use the value property to get the text area contents and store the value in the text variable. In the next line, we invoke the setItem() method of the localStorage object to save the comment text in the localStorage object under the comment key.

Now, the save_comment() function will only run when the save button is clicked. However, proceeding outside the save_comment() function, the lines that follow the function will execute only during the page load.

When the page is first loaded, we use the if statement to check if the localStorage object has data under the comment key. If true, we reference the text area using the Element class and store its instance in the text_area variable. Next, we invoke the write() method of the text_area instance to update the text area contents with the data from local storage.

Make sure your server is running and visit http://0.0.0.0:8000/storage.html. Enter any text you like and click the Save button.

A text area containing text

Next, refresh the URL, and you will see that the text area contains the text you saved on the initial visit.

Our text area, this time populated by text from localStorage

With that, you now know how to leverage localStorage using PyScript. Next, we will read a file in the file system using PyScript.

Interacting with the file system

In this section, we will use PyScript to read data from a plaintext file in the local file system and append its contents into the DOM.

First, let’s create a file containing the data we want to read. In your main project directory, run the following command to create and move into a new directory:

mkdir data &amp;&amp; cd data

Next, create a names.txt file and add the following contents, which are names of Python web frameworks:

Django
Flask
FastAPI
web2p

Save the file and go back to the root of your project directory:

cd ..

With the file created, create a file-system.html file in your text editor with the following:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Read data from file system</title>
    <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
    <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
  </head>
  <body>
   <py-env>
    - paths:
        - /data/names.txt
  </py-env>
  <ul id="frameworks">
  </ul>
  <py-script src="./read-file.py"></py-script>
  </body>
</html>

In the <py-env> tag, we specify the path to the names.txt, which is relative to the file-system.html path. Next, we create an empty <ul> tag with a frameworks ID. Finally, we reference the read-file.py, which we will define soon.

Create a read-file.py with the following contents:

ul_element = document.querySelector("#frameworks")
with open("names.txt") as f:
    for line in f:
        li_element = document.createElement("li")
        li_element.innerText = line
        ul_element.appendChild(li_element)

In the first line, we invoke the querySelector() method with an ID selector #frameworks, which gets a reference of the <ul> element. In the second line, we call the open() method with the filename names.txt and store the file object as f.

Within the with statement, we iterate over each line stored in the file object f. During each iteration, we create an <li> element using the document object’s createElement() method. Next, we set the <li> text content to the value in the line variable using the innerText property of the li_element instance. Finally, we append the <li> element to the <ul> element by calling the appendChild() with the li_element as the argument.

Start the server again (if you stopped it before):

python -m http.server

Visit the http://0.0.0.0:8000/file-system.html URL and you will see the contents from the plaintext file are displayed on the page:

A list of names read from the plaintext file

If you inspect the elements, you’ll see that there are four <li> elements that were appended to the <ul> element.

A list of names inspected in the console

With that, you can now read files in the file system. You can use the same approach to read CSV files and many other file formats.

Conclusion

In this tutorial, we learned how to use the PyScript REPL, create custom modules, use modules from the Python standard library, and import third-party modules. We also learned how to access and manipulate elements using PyScript, make API requests, use localStorage, and read a plaintext file from the file system.

To explore PyScript further, visit the PyScript homepage. In addition, see the Pyodide documentation page to learn more about the possibilities it enables in the browser.

Are you adding new JS libraries to improve performance or build new features? What if they’re doing the opposite?

There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

https://logrocket.com/signup/

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.

Build confidently — .

Stanley Ulili I'm a freelance web developer and researcher from Malawi. I love learning new things, and writing helps me understand and solidify concepts. I hope by sharing my experience, others can learn something from them.

Leave a Reply