A Look At Running Python In A Web Browser With PyScript

PyScript is a framework that allows Python to be run in a browser. It uses HTML along with the power of Pyodide and WebAssembly. This means that the Python runtime runs natively and can make full use of any Python code or available package.

PyScript has some amazing features like bi-directional communication between Python and JavaScript and being able to plug into the browser DOM. This essentially means that you can use PyScript as a drop in replacement for JavaScript for certain tasks. You can also include Python packages (like numpy and matplotlib for example) to create fully featured applications.

As a web developer who has recently been learning more Python, the concept PyScript was very interesting to me.

In this article I will look at how to get up and running with PyScript and what tags are available to make the most of the framework.

Getting Started

Including PyScript into a webpage is quite easy. You just need to include a CSS and a JavaScript file into the header of your HTML document. PyScript allows you to include remote files or download this file and use it locally.

Here is an example of the a simple web page that loads in the remote PyScript runtime and styles.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>PyScript Test</title>

    <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 CSS file is used to add in a few styles for the PyScript framework and although you can technically do without it, having it included will make your life easier.

When you load this page you'll see the following loading dialog, which will show an empty page once PyScript has finished loading.

PyScript loading page, showing a round line and the wording "Loading runtime...".

PyScript introduces eight new HTML tags, four of which are experimental tags that aren't quite safe to use yet. These new tags are as follows:

  • py-script - This is where you create your PyScript code that you want to run within the page.
  • py-repl - This creates a REPL component that allows users to run PyScript through the browser.
  • py-env - Used in the head of the HTML document to declare dependencies that are required for the PyScript code to run.
  • py-config - Set and configure your PyScript application in YAML format.
  • py-box - Experimental - Creates a container that can contain one or more other visual components.
  • py-button - Experimental - Adds a button to the page that can have labels and events attached to it. The actions include on_focus or on_click.
  • py-title- Experimental - Add a text element that acts as the page title.
  • py-inputbox - Experimental - Adds an input box that can be used by users to enter values.

Also existing in the PyScript spec is py-loader, which is used as a loading dialog for the page whilst PyScript is being loaded. Knowing the existence of py-loader is useful information if you are trying to style that loader to suit your own application.

The py-repl Tag

The first thing to try running is the py-repl tag. This will automatically create an interactive Python interpreter (called RELP) within your webpage.

<py-repl id="my-repl"> </py-repl>

You can also include the attribute auto-generate="true" into the py-repl tag to get PyScript to regenerate the tag every time you run a command.

By adding this to our webpage we now have a fully featured Python interpreter.

A screenshot of a webpage running PyScript and showing the py-repl element in action.

This is really nice!

If you want to try this for yourself the the PyScript team have created an example page that has the py-repl tag running. The py-repl tag is a great way of quickly getting up and running with PyScript without installing Python.

I don't know what the security policy is for PyScript; although I'm assuming it is within the browser runtime (ie. self contained) due to the use of WebAssembly and web components. I wouldn't, however, add this to production sites as it can leak information about your system and PyScript application.

The py-script Tag

The main tag for running PyScript code is the py-script tag. This is where you add your Python code that will be run when the page is accessed.

The simplest thing you can do is just print the output of your script using the standard Python print() functions. This will generate a shadow DOM element and inject it into the HTML after the py-script tag.

<py-script>
print('Hello PyScript')
</py-script>

Alternatively, you can use the pyscript.write() function to write the output of your Python script into a named HTML tag on your page. The following code will print the string "Hello PyScript" into the div tag with the id of "destination".

<div id="destination"></div>

<py-script>
pyscript.write('destination', 'Hello PyScript')
</py-script>

Again, this is injected into the DOM as a shadow DOM element.

There's also a shortcut that you can add to the py-script tag called "output", which will write the variable on the last line of the py-script tag to the tag with the output id.

<div id="destination"></div>

<py-script output="destination">
sayhello = 'Hello PyScript'
sayhello
</py-script>

This Python code doesn't do a lot, so let's look at including external Python files using the py-env tag to extend the scripts functionality.

The py-env Tag

You can use the py-script tag just a normal Python code file and include core Python modules at the top of the file. For example, you can include the datetime Python core module and print out the current date like this.

<div id="today"></div>
<py-script output="plot">
    import datetime
    pyscript.write('today', datetime.date.today().strftime('%A %B %d, %Y'))
</py-script>

If you wanted to import Python packages that you would normally install separately you need to use the py-env tag. This is a tag placed onto the page that uses YAML formatted text to import the packages you need.

There are a few packages available that are included through Pyodide. You can't install all packages, but there are quite a selection available, as can be seen on the Pyodide packages page.

As an example, let's include the popular numpy package and generate a random number.

First, we need to create a py-env tag in the page that will tell PyScript to include the numpy package.

<py-env>
  - numpy
</py-env>

Then, we just need to import numpy into the py-script tag and use it. Generating a random number is done using the random.normal() function.

<div id="output"></div>
<py-script>
  import numpy as np
  rand_num = np.random.normal(0,1,1)
  pyscript.write('output', rand_num)
</py-script>

You can also use this tag to import local Python modules that you have written.

As an example, I wanted to include the Python script I wrote that turned the time into a sentence. To do this I created a module called whattime.py and included it in the py-env tag in the following way.

<py-env>
  - paths:
    - ./whattime.py
</py-env>

With this in place it was then just a case of importing the module and running the needed function.

<div id="time"></div>
<py-script defer>
from whattime import translate_time

current_time = time.localtime()

hour = int(time.strftime("%I", current_time))
minute = int(time.strftime("%M", current_time))
am_or_pm = time.strftime("%p", current_time)

time = translate_time(hour, minute, am_or_pm)

pyscript.write('time', time)
</py-script>

This creates a webpage with the text "IT IS TEN TO FIVE PM", which is what the script does.

Conclusion

The py-script tag you can use just like any block of Python code, with some obvious limitations. I tried a few Python examples to see how it worked and whilst it was able to work with files it had some limitations due to the security model of the browser, the use of web components, and WebAssembly. At least, I'm assuming that's the case. I was able to write to a file apparently without error, but once the script finished the file didn't exist anywhere so I'm assuming it was contained within the browser only.

When loading PyScript without any packages the page takes 2-3 seconds to load, with additional packages this jumps to 5-10 seconds. If you can excuse the initial boot times then you essentially have a fully featured and popular scripting language that can interact with the browser.

Compatibility wise, PyScript should run on most modern platforms. WebAssembly is available on most modern browsers and so PyScript should work on Chrome, Firefox, Safari and Edge.

PyScript is in alpha currently and there are a few things in the pipeline to sort out; but it looks like it has great potential. There are some limitations to it's functionality at the moment, mainly the ability to change HTML within the page, but it does have the ability to run Python within the browser, which is a pretty big achievement itself.

One major benefit of PyScript is the ability to write Python code using only a web browser, which essentially means that you can write Python using a tablet or even a phone. This reduces the barrier to entry for writing Python applications and allows new developers the ability to get started quickly with the language.

To my mind, the biggest advantage is that Python developers can easily create a web interface for their applications in PyScript, without having to write JavaScript instead. Since PyScript can communicate with JavaScript it is possible to include JavaScript frameworks to fill in any gaps that PyScript doesn't currently have solutions for. Whilst the PyScript community grows and develops packages for the framework this interoperability allows for backwards compatibility for existing packages.

If you want to know more about PyScript then take a look at the official PyScript website. There's also lots of information in the getting started with PyScript guide that should help answer any questions. If you want to dive deeper there is also an examples directory in the PyScript github repo that has some good examples of how to setup and use PyScript.

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
3 + 5 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.