Challenges with time.sleep and input#

One of the big challenge with educational environments like turtle or robotics is that the programs often need to pause, either to get input from the user with the input function or to show an animation step.

Note

The upcoming Javascript Promise Integration API of WASM will probably allow Pyodide to provide synchronous sleep and input functions working natively. This may well greatly simplify everything.

https://v8.dev/blog/jspi

Pausing execution#

The TigerJython environment typically provides a delay(ms) command that pauses the program execution for ms milliseconds. This is super easy to do in standard Python with the time.sleep(s) synchronuous function. It is another story in the browser which has a completely different execution model and does not support blocking a program by default.

There are different ways to handle this issue, but none is simple and they all require some kind of understanding of the browser inner workings.

Asyncify the code#

One way of implementing a delay function is to use Python coroutines, that is to adapt the code to the asynchronous nature of the browser. This can be easily done with the asyncio module integrated in Pyodide and allows pyodide to wait for the delay.

import asyncio

async def delay(ms):
    await asyncio.sleep(ms / 1000)

async def greet(name):
    print('Hello ')
    await delay(1000)
    print(name)

async def main():
    await greet('Dennis')

asyncio.run(main())

The issue with this code is that it is absolutely inappropriate for beginners. Even professionnal developers often struggle understanding async programming. One solution is to take a student written synchronous program and to generate a corresponding asynchronous program run by Pyodide. This is feasible using the ast module and working on the abstract syntax tree.

However, this trick adds an other layer of complexity for the environment and complicates debugging as Python reports errors relative to the asynchronous program and not the original program written by the students.

Service Workers#

Another way of implementing de delay(ms) function is to use a service worker. Originally, service workers are used to make web applications work offline by implementing advanced caching strategies where HTTP requests are intercepted by the service worker before leaving the browser and responded according to the caching strategy without even reaching the server.

WebAssembly stack switching#