Skip to main content

pyodide_interrupts

This is a package to allow handling of interrupts inside of Pyodide. Pyodide does not have preemptive multitasking. This package enables handling keyboard interrupts in Pyodide.

This defines one context handler check_interrupts(callback, interval) which causes callback to be called every interval instructions.

Simple Example:

>>> def callback(): print("check")
... with check_interrupts(callback, 10):
...    for i in range(50):
...       print(i, end=",")

0,1,check
2,3,4,5,6,check
7,8,9,10,11,check
12,13,14,15,16,check
17,18,19,20,21,check
22,23,24,25,26,check
27,28,29,30,31,check
32,33,34,35,36,check
37,38,39,40,41,check
42,43,44,45,46,check
47,48,49,check

Sketch of usage

In real usage, I use the following callback:

def check_for_interrupt(interrupt_buffer):
    def helper():
        if interrupt_buffer() == 0:
            return
        raise KeyboardInterrupt()
    return helper

interrupt_buffer is a javascript wrapper around a SharedArrayBuffer. On the main thread:

let uuid = uuid();
let interrupt_buffer = new Int32Array(new SharedArrayBuffer(4));
pyodide_worker.postMessage({"cmd" : "execute_python", code, interrupt_buffer, uuid});
let result = await responsePromise(uuid);
// If user cancels, write a nonzero value into our SAB, this will signal pyodide to quit execution of code.
onUserCancel(() => { interrupt_buffer[0] = 2; });

On the pyodide worker thread:

self.messages = {};
function handleExecutePython(msg){
    // Wrap interrupt buffer in a function that gets its value
    // Pyodide Python <==> Javascript bindings don't understand how to get values out of the SAB directly.
    msg.interrupt_buffer = function(){
        return msg.interrupt_buffer[0]; 
    };
    messages[msg.uuid] = msg;
    self.pyodide.globals["handle_message"](uuid);
}

and then the pyodide code:

from js import messages, postMessage
def handle_message(uuid):
    msg = dict(messages[uuid])
    del messages[uuid]
    # Here would use msg["cmd"] to look up handling in a dispatch.
    interrupt_buffer = msg["interrupt_buffer"]
    # check_for_interrupt will raise a KeyboardInterrupt if "onUserCancel" handler is executed on main thread.
    with check_interrupts(check_for_interrupt(interrupt_buffer), 10_000):
        result = run_code(code)
    postMessage({"cmd" : "execute_pyodide_result", "result" : result, "uuid" : uuid })

def run_code(code):
    # Parse code into ast, handle errors, get result out, etc here

Security requirements for SharedArrayBuffer to work

I quote from the MDN docs for SharedArrayBuffer:

As a baseline requirement, your document needs to be in a secure context.

For top-level documents, two headers will need to be set to cross-origin isolate your site:

Cross-Origin-Opener-Policy with same-origin as value (protects your origin from attackers) Cross-Origin-Embedder-Policy with require-corp as value (protects victims from your origin)

Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp

To check if cross origin isolation has been successful, you can test against the crossOriginIsolated property available to window and worker contexts

Building

To build a copy for local use, I recommend creating a virtual environment and then using pip install . in that virtual environment. To upload to pypi, we must build the package for a manylinux ABI to insure that the binaries will be compatible with most systems. The manylinux repository provides docker images with the appropriate old versions of CentOS for us to use to build these. To build, run sudo ./docker_build_wheels.sh. Warning: This will download a ~300mb docker image the first time you do it. Note that you will need to have docker installed for this to work. The resulting wheels will end up in the dist directory and will be suitable for upload to pypi.

[0.1.0] (2020-07-25)

Metadata

Release files for pyodide-interrupts 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyodide-interrupts 0.1.1
File Size Uploaded
pyodide-interrupts-0.1.1.tar.gz 4.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for pyodide-interrupts 0.1.1
File
pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.5+ x86-64 Details
pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl CPython 3.8 CPython 3.8 Linux glibc 2.5+ x86-64 Details
pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl CPython 3.7 CPython 3.7 pymalloc Linux glibc 2.5+ x86-64 Details
pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl CPython 3.6 CPython 3.6 pymalloc Linux glibc 2.5+ x86-64 Details
pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl CPython 3.5 CPython 3.5 pymalloc Linux glibc 2.5+ x86-64 Details

Total release size: 81.5 kB

Release files / pyodide-interrupts-0.1.1.tar.gz

Download URL pyodide-interrupts-0.1.1.tar.gz
Size 4.9 kB
Tags Source
SHA-256 checksum
How to use checksums
b85bc38b92cd5c35dd1a5192a71495abe4cd57eadccfacbc0421fb44fb6c9e74
BLAKE2b-256 checksum
How to use checksums
b1c2918c52e47bf91570d9883a1c761c4d78a59cf4d1d8f8c67c25a4e164ff87
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release files / pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl

Download URL pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl
Size 16.3 kB
Tags CPython 3.9 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
d1f10d3be19a743ec8ffa4c74eb61aedea94387b05173fe978ffbac7cc61c122
BLAKE2b-256 checksum
How to use checksums
84a3ca568ca3c09d84841f0f7bcc527f3568eb63f1596d1ae829dc677ec9f60c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release files / pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl

Download URL pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl
Size 15.6 kB
Tags CPython 3.8 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
33638ea97f3538885ab553a842f37bf38b2e814126da83014e03b638d4414ca4
BLAKE2b-256 checksum
How to use checksums
3167715cc8a3e251553d9eee5880749d4a29cce49a5368d7b7e6971e8aefb39c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release files / pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl

Download URL pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl
Size 14.9 kB
Tags CPython 3.7 CPython 3.7 pymalloc Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
d77d130373cf5aed9633ed21ccdcbc9ba8f86663b89f9152554d9a313ad7c3b1
BLAKE2b-256 checksum
How to use checksums
479e097b6c60fc7e319577bb82431bf14720ba36d968839755d207804894e105
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release files / pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl

Download URL pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl
Size 14.9 kB
Tags CPython 3.6 CPython 3.6 pymalloc Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
3705a4f75e044254823f65585032470fd11f15f74ac2a02fe912f897bf8b233a
BLAKE2b-256 checksum
How to use checksums
24fd8166238e98e32bd839e801350ae3613205eefd39e423d02e729bec35c823
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release files / pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl

Download URL pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl
Size 14.8 kB
Tags CPython 3.5 CPython 3.5 pymalloc Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
455e143635204f5842d6eeefb19088bac4c582ec5bf40925794a5126448e2ed6
BLAKE2b-256 checksum
How to use checksums
6739edee146c3602805261ceaac112bc6bef36e86d5b1aadd02a517137b7129f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

Release history Release notifications | RSS feed

This release

0.1.1 This release

6 release files

0.1.0

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page