PyScript ๐Ÿ๐Ÿ“œ
and the magic ๐Ÿช„ ๐Ÿง™
of Python ๐Ÿ
in the browser ๐Ÿ’ป๐Ÿš€


<!DOCTYPE html>
<html lang="en">
<head>
  <title>A simple PyScript example</title>
  <script defer src="pyscript.js"></script>
</head>
<body>
  <py-script>print("Hello, world")</py-script>
</body>
</html>
          
View

pyscript.js


/*
Create a new custom tag by inheriting from the
HTMLElement class.
*/

class PyScript extends HTMLElement {
    connectedCallback() {
        /*
        Called when the element is first encountered in
        the DOM.
        */
        // Grab the source code.
        const code = this.textContent;
        // Instantiate a "Python interpreter". ;-)
        const re = /"(.*?)"/;
        // Evaluate and emit to STDOUT ;-)
        const output = code.match(re)[0].slice(1, -1);
        this.textContent = output;
    }
}

// Register the class for the given element name.
customElements.define("py-script", PyScript);
          

๐Ÿ˜ฒ


<!DOCTYPE html>
<html lang="en">
<head>
  <title>A simple PyScript example</title>
  <script defer src="pyscript.js"></script>
</head>
<body>
  <py-script>
def hello(name="world!"):
  """
  Return a friendly greeting to the named entity.
  """
  return f"Hello, {name} (from MicroPython)."

print(hello())
  </py-script>
</body>
</html>
          
View

pyscript.js


class PyScript extends HTMLElement {
    connectedCallback() {
        // grab the source code.
        const code = this.textContent;  
        // Remove the code from the DOM.
        this.textContent = "";  
        // JavaScript oh my..! ๐Ÿคฆ
        const self = this;
        // Handle STDOUT events.
        document.addEventListener('micropython-print', 
            function(e) {
                // Just append event data to the textual
                // content of this element.
                const output = self.textContent + e.data;
                self.textContent = output;
            }, 
            false
        );
        // Eval the code.
        mp_js_do_str(code);
    }
}


// Inject MicroPython compiled to WASM into the page, via
// a script tag.
const pyElement = document.createElement("script");
pyElement.src = "micropython.js";
pyElement.onload = function(e) {
    // Start up MicroPython
    let mp_js_startup = Module['onRuntimeInitialized'];
    Module["onRuntimeInitialized"] = async function() {
        mp_js_startup();
        mp_js_init(1024*1024);
        // Register the class for the given element name,
        // only after MicroPython is configured.
        customElements.define("py-script", PyScript);
    }
}
const head = document.getElementsByTagName('head')[0];
head.appendChild(pyElement);
          

๐Ÿ˜ฌ๐Ÿ˜ฒ๐Ÿค”๐Ÿ˜ฑ

Question:

You want to share this Python app with Grandma.


 print("Hello, world!")
          

How?

๐Ÿ˜ฌ๐Ÿ˜ฒ๐Ÿค”๐Ÿ˜ฑ

PyScript is...

...A platform for Python

in the browser.

Antonio's PyBunny ๐Ÿฐ

https://tinyurl.com/h66e32nk


arrr.py

The Black PERL ๐Ÿดโ€โ˜ ๏ธ ๐Ÿฆœโ˜ ๏ธ

https://tinyurl.com/46h66bn9

Runtimes

  • Pyodide
  • MicroPython
  • Lua
  • Ruby
  • ???

import js  # globalThis
          
<button id="click-me">Click me! ๐Ÿญ</button>
          
from js import document


def handler(e):
    """
    It's just Python! Access the DOM!
    """
    output = document.createElement("span")
    output.innerHTML = "๐Ÿ–ฑ๏ธ"
    document.body.appendChild(output)


button = document.querySelector("button#click-me")
button.addEventListener("click", handler)

Clicky Mouse-o-Matic ๐Ÿ

https://tinyurl.com/yc4hjz33

<p><button micropython-click="camera_click">
  Start Camera ๐ŸŽฅ
</button></p>
<video id="video" width="600" height="400" autoplay />
          
import js


async def camera_click(e):
    media = js.Object.new()
    media.audio = False
    media.video = True
    stream = await js.navigator.mediaDevices.getUserMedia(
        media
    )
    video = js.document.querySelector("#video")
    video.srcObject = stream

Lights ๐Ÿ’ก Cameras ๐ŸŽฅ Action ๐Ÿ˜„

https://tinyurl.com/4dtpmrcw

Egg roller (needs LEGO robots) ๐Ÿฅš

https://tinyurl.com/4cc4bd2x

Main thread ๐Ÿงต

from xworker import XWorker

for i in range(12):
    sync = XWorker(
      "pompom.py", config="turtle.toml", type="micropython"
    )

Worker code (1) ๐Ÿข

turtle.speed(8)
turtle.pensize(12)

for i in range(100):
    turtle.penup()
    turtle.setpos(0, 0)
    turtle.left(random.randint(1, 360))
    turtle.pendown()
    turtle.color(random.choice(colours))
    turtle.forward(random.randint(20, 90))

Worker code (2) ๐Ÿ’ฌ

turtle.Screen().show_scene()
result = turtle.svg()

from xworker import xworker

document = xworker.window.document
container = document.createElement("span")
document.body.appendChild(container)
container.innerHTML = result

Turtles on workers ๐Ÿข๐Ÿข๐Ÿข๐Ÿ’ฅ๐Ÿ˜ฑ

https://tinyurl.com/5n8zjj9p

(Chrome only - may melt your laptop.)

Final thoughts

  • PyScript is a platform.
  • It runs everywhere a browser runs.
  • Write code and frameworks on PyScript.
  • It's open source... come play!
  • For the 99% (not just coders).

Stay here for:

  • Running Python packages in the browser with Pyodide ๐Ÿ
    Dr.Roman Yurchak ๐Ÿ‡ซ๐Ÿ‡ท๐Ÿ‡บ๐Ÿ‡ฆ
  • The CPU in your browser: WebAssembly demystified ๐Ÿคท
    Dr.Antonio Cuni ๐Ÿ‡ฎ๐Ÿ‡น
  • Packaging Python Apps with Briefcase ๐Ÿ’ผ
    Dr.Russell Keith-Magee ๐Ÿ‡ฆ๐Ÿ‡บ

๐Ÿ‘‹ Say hello in the corridor track and at the sprints.

Questions..?

TL;DR:

๐Ÿ‘‰pyscript.com๐Ÿ‘ˆ - IDE ๐Ÿ’ป

pyscript.net - docs ๐Ÿ“–

discord.gg/HxvBtukrg2 - chat ๐Ÿ’ฌ

ntoll.org/presentations/ - slides ๐Ÿ–ฅ๏ธ

Image credits

Photo by Dulcey Lima on Unsplash

Photo by Becca Tapert on Unsplash

Photo by Christian Wiediger on Unsplash

Photo by Valery Sysoev on Unsplash

Photo by Mathew Schwartz on Unsplash

Photo by Lia Trevarthen on Unsplash

Photo by Eric Wang on Unsplash