PyScript 101
These past few days, I’ve been playing around with PyScript. I built an interactive cheat sheet for pandas and a cookbook of the most popular Python data visualization libraries.
I’ve learned a few things about how it works, so I thought of putting together these notes in case others may find them useful. This article covers the minimum you should know about PyScript to build a simple web app with it.
I deliberately left out topics that I didn’t find as useful or interesting. But if you want a more detailed introduction, you should read this great tutorial from Real Python.
Let’s get to it!
What’s PyScript?
PyScript is a framework that lets users create Python applications in the browser. It’s built on top of Pyodide, a CPython port to WebAssembly (WASM).
PyScript’s main selling point is that you no longer need a server to use Python and its extensive number of libraries when building a web app. You can plug in PyScript, make a few adjustments, and use many Python libraries in your web app.
People often compare PyScript with Dash and Streamlit. But PyScript works quite differently. It operates on the client side, so no server is required. You could host a web app that uses PyScript for free using services like GitHub Pages.
Dash and Streamlit, on the other hand, require a server, making apps built with these libraries more difficult to deploy and usually more expensive. Furthermore, the server bears the majority of the computational load.
How to Use PyScript
The good thing about PyScript is that there isn’t any installation required. You just need to add it to the head
of your HTML file.
I’ll assume you have a file named index.html
with this content for this and the following sections:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Awesome app!</title>
</head>
<body>
</body>
</html>
The code above is a minimal example we’ll use as a starting point. Next, I’ll show you how to use PyScript. You can do it in two ways:
- Download a copy of the latest version of PyScript, and add the required files to
head
in your HTML document:
<head>
...
<link rel="stylesheet" href="path/to/pyscript.css" />
<script defer src="path/to/pyscript.js"></script>
</head>
- Add the CDN version of PyScript’s JS and CSS files to
head
in your HTML document:
<head>
...
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
PyScript is still under heavy development. If you use the second method, your app may break when new versions are released.
To test your changes locally, use Live Server if you like working with VS Code or try any of these methods if you prefer other code editors.
How to Run Python Code in PyScript
There are two ways to run Python code in PyScript: using py-script
and py-repl
tags. These elements inside go inside body
in your HTML document.
py-script
You can run code using the py-script
tag in two ways:
- Wrap your code with a
py-script
tag.
- Load an external script using the
src
attribute from thepy-script
tag:
The latter is usually preferred to avoid having formatting issues. If you use an HTML auto-formatter, it may break the python code you put inside py-script
.
py-repl
You can also run code using an interactive interpreter, usually known as read–eval–print loop (REPL). Using a REPL makes it feel like you’re running code in a Jupyter notebook.
You can create a REPL with PyScript using the py-repl
tag as follows:
If you try using multiple py-script
and py-repl
in the same page, you may find some unexpected behavior in the output. I came across two issues related to this but it looks like they’ll get fixed soon.
How to Import Libraries
You can make Python libraries available in your environment when your app loads by specifying them in the py-env
tag as follows:
Or you can load them programmatically using micropip
:
How to Interact With HTML Elements
PyScript automatically imports a few things from JavaScript’s global namespace into your Python environment. This means that you can use use these elements without having to import them beforehand. The most important ones are window
, document
, and console
.
window
, and document
, let you read and make changes to elements from the Document Object Model (DOM). While console
lets you interact with your browser’s integrated console.
For example, you could use document
to select a specific element from the DOM:
<body>
...
<py-script>
# Select an element using its ID document.getElementById("input-code") #
Select an element using its class document.querySelector(".table")
</py-script>
...
</body>
Or usedocument
to read attributes from elements and make changes to them, and print information using console
:
<body>
<ul id="users-list">
<li>Dylan</li>
<li>John</li>
<li>Paul</li>
<li>Jane</li>
</ul>
<py-script>
users = ["Dylan", "John", "Jane"] ul = document.querySelectorAll("ul > li")
for li in ul: if li.innerHTML not in users: console.log(li.innerHTML)
li.remove()
</py-script>
</body>
You could also make your Python code react to changes in the DOM. But that requires some magic to work because the web browser cannot natively handle Python functions when an event such as a click on a button happens.
For those cases, Pyodide lets you create proxies that bridge Python functions and JavaScript callbacks. You could use create_proxy
to make your Python code react to changes as follows:
<body>
<input type="text" name="" id="input-text" />
<button type="submit" id="button-submit" for="input-text">Submit!</button>
<div id="text-length"></div>
<py-script>
from pyodide import create_proxy input_button =
document.getElementById("button-submit") def get_text_length(x):
document.getElementById("text-length").innerHTML =
len(document.getElementById("input-text").value)
input_button.addEventListener("click", create_proxy(get_text_length))
</py-script>
</body>
The code lets the user input a text and run the get_text_length
Python function, after he or she clicks on the button on the screen. This function calculates the length of the text that the user entered.
Finally, it’s worth mentioning that PyScript also provides you with the [Element](https://realpython.com/pyscript-python-in-browser/#pyscripts-adapter-for-javascript-proxy)
class. It’s a basic interface that lets you select elements by ID and do certain operations on them. I found it a bit limited, which is why I didn’t cover it in this section.
Other Topics
There are many topics I didn’t cover in this article. So I wanted to provide some resources additional resources I’ve found useful:
- PyScript visual components: PyScript provides a few elements you can use to build the UI of your web app. The Real Python tutorial covers them.
- Accessing the file system: Accessing files is a bit tricky. John Hanley made very detailed tutorials about this topic.
- PyScript and plotly: Getting plotly graphs to work with PyScript is tricky. This article explains how to do it.
- Hosting PyScript: If you don’t need to store data from your users in a server, you can simply host a static page. The easiest way to do that is using GitHub Pages. That’s what I’ve used in my projects.
Conclusion
PyScript is an experimental Python framework that lets you run Python on the web browser. This article covers the basics of PyScript, and will show you how to:
- Use PyScript on a web page
- Run Python code using PyScript
- Interact with the DOM using PyScript
If you have any questions or feedback, let me know in the comments!
Citation
@online{castillo2022,
author = {Castillo, Dylan},
title = {PyScript 101},
date = {2022-09-21},
url = {https://dylancastillo.co/posts/python-pyscript-101.html},
langid = {en}
}