- PyScript: Python on the Web
- What Pyscript Offers
- Browser Support For Python Scripts
- Support for Python libraries
- REPL support for Python
- DOM Support
- Mixing Python With Javascript
- Setting up PyScript
- Open Source Session Replay
- Sample Project Using PyScript
- Add New Memo
- Read Memos
- Update Memo
- Delete Memo
- Conclusion
- More articles from OpenReplay Blog
- Adding Parallax Scroll Animations to React
- Adding Shimmer Effects to React Native apps
- Gain Debugging Superpowers
PyScript: Python on the Web
If you have been following tech news and updates, you must have heard of PyScript. PyScript is a framework that provides in-browser support for Python through an HTML interface; this means you can use all rich libraries Python has to offer, directly at your HTML interface, without server-side support: in other words, you can code your pages using Python instead of JavaScript! PyScript provides Python support in the browser using Pyodide (Pyodide makes it possible to install and run Python packages in the browser) and WebAssembly; It allows you to write Python scripts that are compiled into .wasm format that the browser can run. In addition, PyScript enables injecting Python scripts in your HTML file the same way you’d have a JavaScript file or code block. This framework provides a lot of possibilities for web development, ranging from the support for feature-rich .py libraries to bi-direction communication with javascript; this makes PyScript a vital tool/skill for web development.
What Pyscript Offers
Browser Support For Python Scripts
PyScripts provides browser support for Python scripts without any server-side configuration. In addition, it allows you to inject Python scripts directly into your HTML interface using the py-script tag:
The code block above will print the string “hello world” in your browser: PyScript also allows you to inject .py in the HTML interface using a py-script tag.
Support for Python libraries
PyScript also supports popular Python libraries and packages (NumPy, panda, etc.); this allows you to leverage the features these packages provide when developing your web pages.
REPL support for Python
PyScript provides a REPL injected into the HTML interface; a REPL is an environment where users can enter evaluated inputs. In this instance, PyScript provides an environment that can evaluate python scripts on the browser using the py-repl tag.
DOM Support
Element("text").element.innerText = "Hello from pyscript DOM"
Mixing Python With Javascript
PyScript allows bi-direction communication between Python and JavaScript namespaces; it enables you to use JavaScripts methods in your python script. In this article, we will demonstrate this using the localStorage method:
. PyScript Bi-direction Support
from js import localStorage localStorage.setItem("text", "hello world")
Setting up PyScript
In this section, we will do a walk-through of how to set up a PyScript for your projects; this is a relatively straightforward process using the CDN (Content Delivery Network) link to serve the files. You can find the CDN links for PyScript on the official PyScript website. First, click on the install button on the page and copy the PyScript framework CDN links. Please copy and paste the link and script tag and paste it into your HTML head tag.
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data. Start enjoying your debugging experience — start using OpenReplay for free.
Sample Project Using PyScript
For this article, we will build a memo stored on your browser localStorage using PyScript and Python. The project will allow us to add, read, update and delete memos stored on the browser localStorage . To get started, create a new folder 📂store and an index.html file; repeat the setup process for setting up PyScript from the previous section. The next step will be to create the app.py ****file we will be working with and link the file in index.html .
We will first import javascript methods and initialize the global variables used throughout the project.
NB: It is vital to keep track of the indentation on the project file as this can affect code translation in .py files.
from js import document, localStorage, Object memos = localStorage new_memo = Element('new-memo') add_memo_form = Element('add-memo-form') memo_container = Element('memo-container') update_memo = Element('update-memo') edit_memo_form = Element('edit-memo-form') edit_memo_container = Element('edit-memo-container')
On line 1, we import the JavaScript methods we will be working with; on lines 3-8, we use the PyScript DOM method Element . The Element method accepts the id of an HTML element.
Add New Memo
The first feature will be to add a new memo; to achieve this, we will accept a value keyed into the input with id “new-memo” and add it to the localStorage with a unique key.
def add_new_memo(e): e.preventDefault() localStorage.setItem(get_next_memo_id(), new_memo.element.value) new_memo.element.value = "" get_memos() # Returns an integer that is the next memo id def get_next_memo_id(): # declares an empty python dictionary memo_dict = dict(<>) next_id = 0 # function to loop through local storage and add all the key-value pairs to the python dictionary def memo_loop(memos_entries, _, __): memo_dict[memos_entries[0]] = memos_entries[1] Object.entries(memos).map(memo_loop) # Check for the max id in the dictionary and assign the value to next_id for memo_key in memo_dict: if next_id < int(memo_key): next_id = int(memo_key) return next_id + 1 . add_memo_form.element.onsubmit = add_new_memo
On line 24 from the code block above, we have an onsubmit event on the add_memo_form element assigned add_new_memo function. The add_new_memo function on line 1 accepts an event parameter. On line 3, we save the memo with a key; We generate the memo key by calling the get_next_memo_id function. On line 10, we declare a new Python dictionary, similar to object literals in JavaScript. You can find additional information on dictionaries here. On line 13, we have the function memo_loop that loops through the memos and add the key-value pair to the dictionary memo_dict . On line 17, we loop through the memos and check for the maximum key, assign the value for the maximum key to the next_id variable, and return the next_id incremented by one as the key for a new memo.
NB: Functions in Python are declared using the def keyword.
We call the get_memos function on line 5, which populates the dom with values from memos .
Read Memos
To read memos and populate the HTML DOM with the memo values, we call the get_memos ;
def get_memos(): # Clean inside the memo container lelement memo_container.element.innerHTML = "" # loop through all memo to append them to the memo container Object.entries(memos).forEach(memo_entries_loop) def memo_entries_loop(memo_list, _, __): key = str(memo_list[0]) memo = memos.getItem(key) # Creates new list element and buttons for editing and deleting memo btn_wrapper = document.createElement("div") memo_elem = document.createElement('li') memo_edit_btn = document.createElement( 'button') memo_del_btn = document.createElement('button') # Set classes and id for element btn_wrapper.className = "flex" btn_wrapper.id = key memo_del_btn.className = "delete-btn" memo_edit_btn.className = "edit-btn" memo_elem.className = "memo-" + key memo_edit_btn.innerText = "Edit" memo_del_btn.innerText = "Delete" memo_elem.innerText = memo # Append buttons to list element btn_wrapper.appendChild(memo_edit_btn) btn_wrapper.appendChild(memo_del_btn) memo_elem.appendChild(btn_wrapper) # events memo_del_btn.onclick = delete_memo memo_edit_btn.onclick = open_edit_container # append the new memo to the container memo_container.element.appendChild( memo_elem)
On line 5, we loop through memos with the memo_entries_loop function; on lines 11 through 15, we create the HTML elements that will hold the memo values. Then, on line 18, we assign the key for the btn_wrapper element that appends the edit and delete button on lines 26 and 27. Finally, on line 30, we add an onclick event to the memo_del_btn button with the value delete_memo and assign the open_edit_container function to the onclick event for the memo_edit_btn button. Next, we will append the memo value to the memo_elem element on line 24 and the btn_wrapper on line 28. Following this, we append the memo_elem to the memo_container on line 33.
Update Memo
The edit button from the code block in the previous section triggers open_edit_container ;
# Function to toggle the edit container def open_edit_container(e): memo_id = e.target.parentNode.id edit_memo_container.element.classList.add("open") edit_memo_form.element.className = memo_id update_memo.element.value = memos.getItem(memo_id)
This function gets the memo id from the id of the parent element on line 3 and adds the “open” class to the edit_memo_container , triggering the edit modal to be visible. Next, we assign the key for the memo to edit to edit_memo_form on line 6 and assign the memo value to update_memo .
. def edit_memo(e): e.preventDefault() memo_id = e.target.classList memos.setItem(memo_id, update_memo.element.value) close_edit_container() get_memos() . def close_edit_container(): edit_memo_form.element.className = "" update_memo.element.value = "" edit_memo_container.element.classList.remove("open") . edit_memo_form.element.onsubmit = edit_memo
From the code block above, we have an onsubmit event for the edit_memo_form element that calls the edit_memo function. Then, on line 4, we assign the memo id to edit from the event target( edit_memo_form ) and set the memo to the current value of the update_memo input element, call the close_edit_container function to reset the edit form and input element. Finally, we close the edit_memo_container modal by removing the ‘open’ class and repopulate the DOM with the updated memos by calling the get_memos function.
The close_edit_container is also passed to the modal’s close button using the py-onClick attribute.
Delete Memo
To handle deleting a memo, we have the delete_memo function;
# Function to delete a memu using the key passed to parent as id def delete_memo(e): memo_id = e.target.parentNode.id memos.removeItem(memo_id) get_memos()
On line 3, we get the key for the current memo to be deleted from the parent element id, remove the memo that matches the key from memos / localStorage , and call the get_memos function to update the DOM elements with the updated memos .
Conclusion
PyScript is a good framework with a lot to offer. However, I think PyScript won’t replace JavaScript for web development. You can find the complete code for the project in this GitHub Repository. To play around with the live application, visit https://pyscript-one.vercel.app/.
More articles from OpenReplay Blog
Adding Parallax Scroll Animations to React
Adding Shimmer Effects to React Native apps
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs and track frustrations in your app. Get complete visibility into your frontend with OpenReplay, the most advanced open-source session replay tool for developers.