Skip to main content

Introduction to PyScript

Shen Zhen, China

Hello World

PyScript allows you to run Python in HTML. To use PyScript you can either download it and follow the instructions, or add the following lines to your page:

<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>

I downloaded them and placed them inside a folder I called alpha next to my HTML file. The official Hello World example - modified to work offline - then looks like this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PyScript Hello World</title>
<link rel="stylesheet" href="/alpha/pyscript.css" />
<script defer src="/alpha/pyscript.js"></script>
</head>
<body> <py-script> print('Hello, World!') </py-script> </body>
</html>

I found that PyScript downloaded the JS map from the CDN pyscript.js.map. This has to be placed next to the pyscript.js file. And I also received a 404 from my browser when PyScript tried to download a file called pyscript.py. This does not seem to be present on the CDN link (?). But I found it inside the PyScript Repo on Github and placed it next to the pyscript.js file.

Notice the use of the <py-script> tag in the HTML body. This is where you'll write your Python code. In the following sections, we'll introduce the eight tags provided by PyScript.

When you take a look into the pyscript.js file you will find out that it is using Pyoide.js. A quick look at the homepage tells us:

Pyodide is a port of CPython to WebAssembly/Emscripten.

Pyodide makes it possible to install and run Python packages in the browser with micropip. Any pure Python package with a wheel available on PyPI is supported. Many packages with C extensions have also been ported for use with Pyodide. These include many general-purpose packages such as regex, pyyaml, lxml and scientific Python packages including numpy, pandas, scipy, matplotlib, and scikit-learn.

Pyodide comes with a robust Javascript ⟺ Python foreign function interface so that you can freely mix these two languages in your code with minimal friction. This includes full support for error handling (throw an error in one language, catch it in the other), async/await, and much more.

The CDN that is used here is, unfortunately blocked in China:

const DEFAULT_RUNTIME = {
src: 'https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js',
name: 'pyodide-default',
lang: 'python',
};

So let me download the entire build from Github instead (151 MB which expands to ~260MB) and place it inside a folder Pyodide next to my index.html file. Following the development guide I need to spin up a Python web server that is configured to set the correct headers from inside this folder:

python -m http.server

This will serve all necessary Pyodide files on localhost:8000. So all I need to do is to change the CDN link inside the pyodide.js file to:

const DEFAULT_RUNTIME = {
src: 'http://localhost:8000/pyodide.js',
name: 'pyodide-default',
lang: 'python',
};

Now running two web servers - the Python server for Pyodide on port 8000 and a Node.js one for my html file on port 3000 I am finally able to execute the Hello World PyScript!

PyScript

PyScript Tags

  • <py-script>
    • The <py-script> tag allows you to write your Python code directly into your HTML page. Anything in between those tags is going to be interpreted as Python.
  • <py-env>
    • The <py-env> tag allows you to import additional Python modules and packages outside of the Python Standard Library.
  • <py-repl>
    • The <py-repl> tag starts a REPL (Read-Evaluate-Print-Loop) session that allows you to live execute python commands and code.

Py-Script

We already saw a first example of the <py-script> tag in the Hello World above:

<body> <py-script> print('Hello, World!') </py-script> </body>

But the tag can also direct it's output to an HTML tag ID somewhere in your page:

<py-script output="output-div"> print('Hello, World!') <py-script>

Or it can load a Python script file from somewhere else:

<py-script src="/my-python-script.py"><py-script>

You can make use of all the Standard Libraries that come with Python, e.g. datetime:

<body>
<h2>Date & Time Example</h2>
<py-script>
import datetime as dt
Element('date').write(dt.date.today().strftime('%A %B %d, %Y'))
</py-script>
<p>Today is: <label id="date"></label></p>
</body>

PyScript

Py-Env

Use the <py-env> tag to define your Python dependencies:

<py-env>
- numpy
- matplotlib=3.5.2
- paths:
- /utils.py
</py-env>

For example add a scatter plot to your web page with:

<head>
<py-env>
- numpy
- matplotlib
</py-env>
</head>

<body>
<py-script output="scatter">
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(1000)
y = np.random.randn(1000)
fig, ax = plt.subplots()
ax.scatter(x,y)
fig
</py-script>
<div id="scatter"></div>
</body>

PyScript

Py-REPL

Use the <py-repl> tag to generate a REPL widget and place it on the page:

<py-repl id="interface" auto-generate="true"> </py-repl>

This widget can also be used to output system messages to the user:

<py-repl id="log" auto-generate="true" std-out="output" std-err="err-div"> </py-repl>

The REPL command interface has to be wrapped inside a <pybox> tag to automatically add some styles - like:

<py-box widths="2/3;1/3">
<py-repl id="py-repl" auto-generate="true" std-out="repl-output" std-err="err-out"> </py-repl>
<div id="repl-output"></div>
</py-box>
<footer id="err-out"></footer>

PyScript

Working with Forms

Creating a form that takes user input and displays it on the page:

<py-script>
from js import console

def send(*args, **kwargs):
text = Element('input').element.value
Element('output').element.innerText = text
</py-script>
<input type="text" id="input" placeholder="Type something..." style="border: 2px; border: black; border-style: outset;" />
<button id="submit" type="submit" pys-onClick="send">OK</button>
<div id="output"></div>

PyScript