PyScript - Python nel Browser
Pubblicato da Michele Saba
Il PyCon US 2022 resterà nella storia come l'evento in cui il CEO e co-founder di Anaconda ha presentato al mondo un nuovo framework per la creazione di applicazioni per browser con Python: PyScript. Con PyScript è possibile eseguire del codice Python direttamente all’interno di un file HTML senza aver bisogno di utilizzare nient’altro! Vediamo insieme come funziona, come utilizzarlo per implementare Python in una pagina web e alcuni esempi concreti di utilizzo.
A che cosa serve PyScript?
La motivazione dietro alla creazione di PyScript sembrerebbe la volontà da parte di Anaconda di rendere Python un linguaggio ancora più completo permettendo a tutti i suoi utilizzatori di non dover imparare JavaScript ad esempio per creare dei siti. Infatti se da una parte Python dispone di un ricchissimo ecosistema per la creazione del back-end dei siti, per la creazione di tutte le componenti interattive lato client si deve comunque far affidamento a JavaScript e questa è sicuramente una penalità per tutti quegli sviluppatori che utilizzano Python e non hanno tempo di imparare un altro linguaggio.
Oltre a semplificare il processo di creazione di siti e applicazioni un framework come PyScript risolve anche il problema della distribuzione del prodotto finito: la fase di deployment (ovvero la messa on line dell'applicazione) nel caso di siti web verrebbe sostanzialmente a mancare perché tutto avviene all'interno del browser.
Inoltre qualsiasi dispositivo connesso in rete dispone di un browser quindi PyScript renderebbe Python assolutamente accessibile a tutta quella fetta della popolazione che si trova primariamente a lavorare lato client come ad esempio sviluppatori front-end o creativi e offrirebbe un'ottima soluzione per i problemi di packaging e distribuzione dell’ecosistema Python. Con PyScript il codice Python si trova all'interno del codice HTML delle pagine web, e questo permette ad esempio la condivisione di dashboard e modelli che possono essere condivisi in maniera davvero semplice e aperti con un qualsiasi browser web.
ATTENZIONE: PyScript è ancora in uno stadio sperimentale e non ha una versione stabile. Il framework è ancora in fase di sviluppo e non è adatto all'utilizzo in produzione.
Come installare PyScript
Andiamo nel sito ufficiale di PyScript, in cui possiamo per prima cosa visionare la documentazione. Per scaricare PyScript e vedere alcuni esempi del suo utilizzo possiamo clonare il repository di GitHub o scaricare lo zip che contiene i file del progetto direttamente dal pulsante Install sulla Homepage del sito.
Per integrare le funzionalità di PyScript in un progetto è sufficiente aggiungere le seguenti righe nell’header del nostro file HTML:
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
Esempi di utilizzo di PyScript
Se stiamo utilizzando anche uno script di Python aprire semplicemente il file HTML all'interno del browser non è sufficiente a renderizzare le pagine correttamente e a far funzionare PyScript: dobbiamo utilizzare un server.
Se utilizziamo Visual Studio Code come editor possiamo semplicemente installare l'estensione Live Server, che ci permette di aprire in un server le pagine o cliccando con il tasto destro del mouse e selezionando “Open with Live Server” o tramite la combinazione di tasti (alt+L, alt+O) per avviare il server e (alt+L, alt+C) per interromperlo.
In alternativa possiamo utilizzare il modulo della Standard Library di Python http.server. Entriamo da terminale nella cartella examples di PyScript e digitiamo il seguente comando per avviare un server HTTP locale sulla porta 8000:
python -m http.server
Adesso all’indirizzo http://localhost:8000/ avremo il file index.html della cartella examples, che ci fornisce la lista degli script che possiamo aprire:
Apriamo Hello World e analizziamo il file hello_world.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>PyScript Hello World</title>
<link rel="icon" type="image/png" href="favicon.png" />
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<link rel="stylesheet" href="./assets/css/examples.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<nav class="navbar" style="background-color: #000000">
<div class="app-header">
<a href="/">
<img src="./logo.png" class="logo" />
</a>
<a class="title" href="" style="color: #f0ab3c">Hello World</a>
</div>
</nav>
<py-tutor>
<py-config>
plugins = ["https://pyscript.net/latest/plugins/python/py_tutor.py"]
</py-config>
<section class="pyscript">
Hello world! <br />
This is the current date and time, as computed by Python:
<py-script>
from datetime import datetime
now = datetime.now()
display(now.strftime("%m/%d/%Y, %H:%M:%S"))
</py-script>
</section>
</py-tutor>
</body>
</html>
Possiamo vedere che il file include i tag che abbiamo visto nella Homepage del sito: sono i file pyscript.css e pyscript.js forniti direttamente da pyscript.net. All'interno del tag body notiamo il tag HTML py-script con del codice Python che, se eseguito, ci fornisce la data e l’ora attuali:
from datetime import datetime
now = datetime.now()
display(now.strftime("%m/%d/%Y, %H:%M:%S"))
Infatti se dal server apriamo l’esempio Hello World, troviamo la data e l’ora correnti. Se andiamo all’indirizzo http://localhost:8000/antigravity.html possiamo vedere in azione una vignetta di xkcd che parla della potenza degli import di Python:
Tenete presente che tutti questi esempi possono essere visualizzati anche direttamente dal sito di PyScript senza dover scaricare nessun file.
Come usare Python in una pagina HTML con PyScript
Creiamo un nuovo file HTML chiamato pyscript-example.html e includiamo prima della chiusura del tag head i due link forniti da PyScript:
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyScript!</title>
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
</body>
</html>
L'obiettivo di questo esempio è mostrare nel browser la versione di Python utilizzata alla pressione di un tasto presente all'interno della pagina.
Aggiungiamo un paragrafo e un tasto
Modifichiamo il body aggiungendo un titolo, un elemento button e in mezzo ad essi un paragrafo vuoto, in cui inseriremo il codice Python. Aggiungiamo un id “output” all'interno del paragrafo e un id “myBtn” al tasto.
<body>
<h1>Python Version</h1>
<p id="output"></p>
<button id="myBtn" type="button">Mostra Versione Python</button>
</body>
Ora che la pagina è pronta possiamo iniziare ad aggiungere il nostro codice Python. Poco prima del tag body di chiusura aggiungiamo il tag py-script e importiamo il modulo sys, rimanendo il più possibile alla sinistra del documento per evitare errori di indentazione.
Creiamo una funzione all'interno del tag py-script
Definiamo una funzione show_python_version e facciamo in modo che accetti *args e **kwargs come parametri perché PyScript passerà automaticamente dei parametri alle nostre funzioni come ad esempio parametri relativi agli eventi che possono averle invocate. Per identificare il paragrafo in cui verrà mostrato il risultato del codice definiamo la variabile output_paragraph a cui assegniamo la classe Element a cui passiamo l’id “output” come parametro.
Element è una classe Python di PyScript: quando creiamo un oggetto di tipo Element facendo riferimento a uno specifico id presente nella pagina HTML possiamo utilizzare una serie di metodi specifici per potere effettuare delle modifiche, ad esempio scrivere del contenuto all'interno dei tag. In questo caso noi vogliamo mostrare la versione di Python che sta utilizzando PyScript, quindi definiamo un’altra variabile version a cui associamo sys.version e con il metodo write aggiungiamo version al paragrafo con una f-string.
<py-script>
import sys
def show_python_version(*args, **kwargs):
output_paragraph = Element(element_id="output")
version = sys.version
output_paragraph.write(f"Version: {version}")
</py-script>
NOTA: Il procedimento che segue è leggermente diverso da quello del video perché nel frattempo PyScript è stato aggiornato: per scrivere il contenuto nella pagina HTML adesso si utilizza il selettore py-click al posto di pys-onClick e contrariamente a come spiegato nel video ora è necessario utilizzare le parentesi quando gli si assegna la funzione da richiamare.
Facciamo il modo che il tasto chiami la funzione con il tag py-click
Per fare modo che la funzione show_python_version venga eseguita alla pressione del tasto button aggiungiamo il tag py-click a cui passiamo il nome della funzione invocandola con le parentesi.
<button id="myBtn" type="button" py-click="show-python-version()">Mostra Versione Python</button>
Torniamo ora nel browser e possiamo vedere la versione di Python che stiamo utilizzando con PyScript.
Modifichiamo la pagina con Bootstrap
Aggiungiamo il link al CSS di Bootstrap nell'head per fare delle modifiche allo stile alla pagina:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
Aggiungiamo le classi btn e btn-outline-info al nostro tasto, aggiungiamo la classe container per aggiungere spazio ai lati della pagina e all'interno del tag paragrafo con id “output” aggiungiamo come contenuto “Version:” in modo che la scritta venga mostrata prima dell’output della funzione show_python_version:
<div class="container">
<h1>Python Version</h1>
<p id="output">Version:</p>
<button id="myBtn" class="btn btn-outline-info" type="button" py-click="show_python_version()">Mostra Versione Python</button>
</div>
Se riavviamo il server, vedremo la nostra pagina con le modifiche:
Come funziona PyScript?
A questo punto forse vi starete probabilmente chiedendo come sia possibile fare tutto quello che abbiamo fatto finora con PyScript utilizzando solo il browser senza nemmeno installare Python. Per capirlo, pensiamo al browser come ad una macchina virtuale e con questo concetto in mente introduciamo Web Assembly o WASM.
Web Assembly è uno standard sviluppato dal World Wide Web Consortium (W3C) e include un linguaggio di basso livello simile ad assembly che può essere rappresentato in forma testuale e quindi convertito in formato binario per l'esecuzione nel browser con velocità comparabili al codice macchina nativo.
Web Assembly che viene utilizzato come target di compilazione per altri linguaggi di programmazione come ad esempio C o C++. Nel nostro caso il salto verso Python viene fatto grazie a Pyodide, un porting CPython verso Web Assembly tramite Emscripten, che a sua volta è uno degli strumenti più usati per la compilazione in WASM.
In questa pagina di Anaconda Nucleus troviamo un grafico che riassume come funziona PyScript:
Abbiamo quindi come base WASM e Pyodide, su cui è costruito PyScript, che aggiungiunge Tag, Widget, Namespace e molto altro.