A few days ago, the Anaconda project announced the PyScript framework, which allows Python code to be executed directly in the browser. Additionally, it also covers its integration with HTML and JS code.
An execution of the Python code in the browser is not new; the pyodide project has allowed this for a long time (by compiling Python to WebAssembly), but what’s new here is the integration with the rest of the browser ecosystem. Thanks to PyScript, we can easily include many modules directly from the pip repository: all modules written in “pure” Python should work, and some modules requiring native code have also been recompiled into WebAssembly.
Python has a very large standard library, as well as many great external libraries, so this project opens up many interesting opportunities to quickly build simple tools like security tests, or to allow showcasing some training concepts.
Basics of PyScript
Let’s take a look at a very simple code written in PyScript:
<!doctype html>
<html>
<head>
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<py-script>
from js import alert
alert("Securitum says hi!")
</py-script>
</body>
</html>
As you can see, all we need is to load the script, and then we can write python code in a special <py-script> tag. In the example above, I have used the js module built into the PyScript, which allows us to directly reference JavaScript functions. So, as you can guess, after loading the above page, you will see an alert with the text “Securitum says hi!”.
Greater interaction with JS
Let’s try to interact a bit more with JS. I will write a simple script that will use the python secrets module to generate random tokens. These tokens will be generated when the button is pressed and displayed in another HTML element. Here is an example implementation:
<!doctype html>
<html>
<head>
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<button>Click me</button>
<div>The random token is: <b id=token></b></div>
<py-script>
from js import document,alert
from pyodide import create_proxy
import secrets
def onclick(ev):
pyscript.write("token", secrets.token_hex(16))
button = document.querySelector("button")
button.addEventListener("click", create_proxy(onclick))
</py-script>
</body>
</html>
- If we want JS code to be able to execute a function defined in PyScript, we need to wrap it up by calling create_proxy.
- PyScript provides the pyscript.write method that allows you to assign HTML directly to an element with a given ID. So there is no need to reference document.getElementById (though it would be possible).
And below, let’s see the code in action:
Click me
Random token is: da9315d5adc6b790aa3524d9e1e80090
Importing modules from pip
While the use of modules from a standard library ends with the use of a normal import, some additional steps need to be taken if we want to load the module from the pip repository.
To name it: a special tag <py-env> has to be added in HTML. In that tag, we define a list of external modules. For example, if we wanted to import a primefac, we have to use the tag beforehand:
<py-env>
- primefac
</py-env>
And in the following code, the basic import primefac will work.
primefac is a library useful for factoring numbers. So let’s write a very simple script that uses it to factorize a user-supplied number. Here is the code:
<!doctype html>
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<py-env>
- primefac
</py-env>
<p><label>Enter an integer in the range from 1 to 10000: <input id=n></label></p>
<p>The prime factors are:: <span id=factors></span></p>
<py-script>
import primefac
from pyodide import create_proxy
input = document.querySelector("#n")
def oninput(ev):
num = int(ev.target.value)
num = min(num, 10000)
num = max(num, 1)
factors = list(primefac.primefac(num))
pyscript.write("factors", factors)
input.addEventListener("input", create_proxy(oninput))
</py-script>




