Python Hands-on

Intro to PyScript: Run Python in your web browser

PyScript lets you run Python scripts right in the browser, side by side with JavaScript, with two-way interaction between your code and the web page.

Python notebook analytics
dTosh / Shutterstock

Created by Anaconda and launched in April 2022, PyScript is an experimental but promising new technology that makes the Python runtime available as a scripting language in WebAssembly-enabled browsers.

Every commonly used browser now supports WebAssembly, the high-speed runtime standard that languages like C, C++, and Rust can compile to. Python's reference implementation is written in C, and one earlier project, Pyodide, provided a WebAssembly port of the Python runtime.

PyScript, though, aims to provide a whole in-browser environment for running Python as a web scripting language. It builds on top of Pyodide but adds or enhances features like the ability to import modules from the standard library, use third-party imports, configure two-way interactions with the Document Object Model (DOM), and do many other things useful in both the Python and JavaScript worlds.

Right now, PyScript is still a prototypical and experimental project. Anaconda doesn't recommend using it in production. But curious users can try out examples on the PyScript site and use the available components to build experimental Python-plus-JavaScript applications in the browser.

In this article, we'll take a tour of PyScript, and see how it facilitates Python and JavaScript interactions in your web apps.

Programming with PyScript

At its core, PyScript consists of a single JavaScript include that you can add to a web page. This include loads the base PyScript runtime and automatically adds support for custom tags used in PyScript.

Here's a simple example of a "Hello, world" project in PyScript:


<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet"
    href="https://pyscript.net/releases/2023.11.2/core.css" />
    <script type="module"
    src="https://pyscript.net/releases/2023.11.2/core.js">
    </script>
</head>
<body>
    <script type="py" terminal>
        from pyscript import display
        display("Hello World!")
        print("Hello terminal!")
    </script>
</body>
</html>

The script tag in the document's head loads the core PyScript functionality. The .css stylesheet is optional, but useful. Among other things, it inserts notices to the user at the page's load time about what the page is doing—loading the Python runtime, initializing, and so on.

Python code is enclosed in the script tag with a type="py" attribute. Note that the code should be formatted according to Python's conventions for indentation, or it won't run properly. Be aware of this if you use an editor that reformats HTML automatically; it might mangle the contents of the script block and make it unrunnable. You can also refer to a .py file rather than include the script inline, which may be easier.

Any Python code is evaluated once the PyScript components finish loading. You can choose whether the output is sent to the DOM (use pyscript.display), or to an embedded terminal. If you use the terminal, you have to include terminal as an attribute on the script tag. (More about this below.)

If the script in the tags writes to stdout (as with a print statement), you can direct where you want the output displayed on the page by supplying an output property. In this example, stdout for the script gets directed to the div with the ID of "out".

If you save this into a file and open it in a web browser, you'll first see a "loading" indicator and a pause, as the browser obtains the PyScript runtime and sets it up. The runtime should remain cached on future loads but will still take a moment to activate. After that, Hello world should appear on the page twice—once at the top in HTML, and once in a black pane that is the embedded terminal.

Standard library imports

Scripts using Python's builtins alone are only somewhat useful. Python's standard library is available in PyScript the same way you'd use it in regular Python: simply import and get to work. Standard library imports should just work in PyScript.

If you wanted to modify the above script block to display the current time, you wouldn't need to do it any differently than you would in conventional Python:


import datetime
print ("Current date and time:",
    datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S"))

Using libraries from PyPI

What if you want to install a package from PyPI and use that? PyScript lets you specify  project configurations, including any third-party packages to be installed from PyPI, by way of a .toml or .json format file in your project's directory. Let's see how it works using .toml.

To use the project config file, you'll need to include the config directive in your script tag:


<script type="py" src="main.py" config="pyscript.toml">

The pyscript.toml file lists any needed packages:


packages = ["package","another-package"]

Note that not all packages from PyPI will install and run as expected. Most "pure" Python packages, like humanize, should run fine. And packages used in the examples provided by Anaconda, like numpy, pandas, bokeh, or matplotlib, will also work. But packages that require network access or work with platform-native elements like GUIs are not likely to work.

Importing locally

For another common scenario, let's say you want to import from other Python scripts in the same directory tree as your web page. Using imports makes it easier to move more of your Python logic out of the web page itself, where it's intermixed with your presentation and may become difficult to work with.

Normally, Python uses the presence of other .py files in the file system to indicate what it can import. PyScript doesn't work this way, so you'll need to specify which files you want to make available as importable modules.

To do this, you list the URLs you want to make available to PyScript in your application's config file in a [files] block, along with how you want to map them to PyScript's emulated filesystem. For instance:


[files]
"/module.py" = "./libs/module.py"
"https://mydata.com/data.csv" = "./data.csv"

Whatever file is accessible from the URL on the left is made available to the Python interpreter's emulated filesystem via the path on the right. In this case, the file you'd see if you browsed to /module.py (e.g., http://localhost:8000/module.py) is available to Python as libs.module. Likewise, the file at the URL https://mydata.com/data.csv is available in the emulated current working directory as data.csv.

The in-browser terminal

Python users should be familiar with the REPL, the console interface to the Python runtime. In PyScript, you can embed into the browser a live terminal running the REPL, or just console output from your Python program.

To embed a terminal, use a script tag that has terminal as one of its attributes:


<script type="py" terminal>print("hello world")</script>

This opens a terminal and prints hello world, but does not allow any interactivity. For interaction, you need to use the worker attribute:


<script type="py" terminal worker>
name = input("What is your name? ")
print(f"Hello, {name}")
</script>

The worker runs your program in a web worker, which is essentially a subprocess. Note that you cannot use web workers on an HTML file loaded locally; you must load it from a web server that provides certain headers. PyScript's documentation explains how this works in detail.

Most of what's possible in a regular console, like coloring and Unicode, should be supported in the PyScript terminal, too.

Interacting with the DOM and JavaScript

Because PyScript is based on browser technology, it has mechanisms for interacting with the DOM. For instance, if you wanted to get the value of an input box on a web page and use it in your Python code, you'd do this:


from pyscript import window, document
inputbox = document.querySelector("#my-input")
print("Value of input:", inputbox.value)

PyScript also includes a module called pydom that allows dynamic creation of objects on the page:


from pyweb import pydom
new_div = pydom.create("div")
new_div.content = "Hello World"

This creates a new div element on the page and populates it with text. Most of the other kinds of manipulations you can perform with the DOM in JavaScript—such as adding elements and changing attributes—can be done through the pydom library.

Copyright © 2024 IDG Communications, Inc.