Introduction to PyScript
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 thepyscript.js
file. And I also received a 404 from my browser when PyScript tried to download a file calledpyscript.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 thepyscript.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 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.
- The
<py-env>
- The
<py-env>
tag allows you to import additional Python modules and packages outside of the Python Standard Library.
- The
<py-repl>
- The
<py-repl>
tag starts a REPL (Read-Evaluate-Print-Loop) session that allows you to live execute python commands and code.
- The
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>
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>
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>
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>