Convert Figma logo to code with AI

wasmerio logowasmer-python

🐍🕸 WebAssembly runtime for Python

1,992
79
1,992
73

Top Related Projects

11,967

Pyodide is a Python distribution for the browser and Node.js based on WebAssembly

Emscripten: An LLVM-to-WebAssembly Compiler

6,727

The WebAssembly Binary Toolkit

18,439

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten

4,064

Lucet, the Sandboxing WebAssembly Compiler.

Quick Overview

Wasmer-python is a Python extension that allows running WebAssembly (Wasm) modules natively and efficiently in Python. It provides a seamless integration between Python and WebAssembly, enabling developers to leverage the performance and portability of Wasm within their Python applications.

Pros

  • High performance: Executes WebAssembly modules at near-native speed
  • Cross-platform compatibility: Runs on various operating systems and architectures
  • Easy integration: Seamlessly incorporates WebAssembly modules into Python projects
  • Rich ecosystem: Supports multiple Wasm compilers and runtimes

Cons

  • Learning curve: Requires understanding of WebAssembly concepts
  • Limited to Wasm-compatible languages: Not all programming languages can be compiled to WebAssembly
  • Potential security concerns: Care must be taken when executing untrusted Wasm modules
  • Dependency on external Wasm modules: Requires separate compilation of modules to Wasm format

Code Examples

  1. Loading and instantiating a Wasm module:
from wasmer import engine, Store, Module, Instance
from wasmer_compiler_cranelift import Compiler

store = Store(engine.JIT(Compiler))
module = Module(store, open('example.wasm', 'rb').read())
instance = Instance(module)
  1. Calling a Wasm function from Python:
result = instance.exports.add(5, 37)
print(result)  # Output: 42
  1. Passing complex data types to Wasm:
from wasmer import wasi

wasi_version = wasi.get_version(module, strict=False)
wasi_env = wasi.StateBuilder('example').finalize()
instance = wasi.Wasi(wasi_version).instantiate(module, wasi_env, store)

result = instance.exports.process_array([1, 2, 3, 4, 5])
print(result)

Getting Started

  1. Install Wasmer-python:

    pip install wasmer wasmer_compiler_cranelift
    
  2. Create a simple Wasm module (e.g., in Rust) and compile it to example.wasm.

  3. Use the following Python code to run the Wasm module:

    from wasmer import engine, Store, Module, Instance
    from wasmer_compiler_cranelift import Compiler
    
    store = Store(engine.JIT(Compiler))
    module = Module(store, open('example.wasm', 'rb').read())
    instance = Instance(module)
    
    result = instance.exports.your_function(args)
    print(result)
    

Competitor Comparisons

11,967

Pyodide is a Python distribution for the browser and Node.js based on WebAssembly

Pros of Pyodide

  • Runs Python and scientific libraries directly in the browser
  • Seamless integration with JavaScript, allowing bidirectional communication
  • Supports a wide range of scientific computing libraries (NumPy, Pandas, Matplotlib)

Cons of Pyodide

  • Larger download size due to included Python interpreter and libraries
  • Limited to browser environments, not suitable for server-side or desktop applications
  • May have performance overhead compared to native Python execution

Code Comparison

Pyodide:

from pyodide import loadPackage, runPython

await loadPackage('numpy')
result = runPython(`
    import numpy as np
    x = np.array([1, 2, 3])
    x.mean()
`)

Wasmer-Python:

from wasmer import engine, Store, Module, Instance

module = Module(store, wasm_bytes)
instance = Instance(module)
result = instance.exports.mean([1, 2, 3])

Pyodide focuses on running Python code in the browser, while Wasmer-Python provides a more general-purpose WebAssembly runtime for Python. Pyodide is better suited for scientific computing in web applications, whereas Wasmer-Python offers broader WebAssembly integration capabilities across various environments.

Emscripten: An LLVM-to-WebAssembly Compiler

Pros of Emscripten

  • Mature and widely adopted toolchain for compiling C/C++ to WebAssembly
  • Extensive documentation and community support
  • Provides a complete ecosystem with built-in JavaScript APIs and browser integration

Cons of Emscripten

  • Larger runtime overhead compared to pure WebAssembly solutions
  • Primarily focused on web-based applications, less versatile for other environments
  • Steeper learning curve for developers not familiar with C/C++

Code Comparison

Emscripten (C++ to JavaScript):

#include <emscripten.h>
#include <iostream>

EMSCRIPTEN_KEEPALIVE
extern "C" int add(int a, int b) {
    return a + b;
}

Wasmer Python:

from wasmer import Store, Module, Instance

store = Store()
module = Module(store, open('add.wasm', 'rb').read())
instance = Instance(module)
result = instance.exports.add(5, 3)
print(result)  # Output: 8

Emscripten focuses on compiling C/C++ to WebAssembly with JavaScript integration, while Wasmer Python provides a runtime for executing WebAssembly modules directly in Python. Emscripten is more suited for web applications, whereas Wasmer Python offers greater flexibility for running WebAssembly in various environments.

6,727

The WebAssembly Binary Toolkit

Pros of wabt

  • More comprehensive WebAssembly toolset, including text format conversion and validation
  • Longer development history and wider community adoption
  • Supports multiple programming languages through bindings

Cons of wabt

  • Primarily focused on WebAssembly tools, not a runtime environment
  • May require more setup and configuration for specific use cases
  • Less integrated Python-specific functionality

Code Comparison

wabt (C++):

#include "src/binary-reader.h"
#include "src/error-formatter.h"

std::unique_ptr<Module> ReadModule(const std::string& filename,
                                   Errors* errors) {
  return ReadModule(filename, kWasmFeatures, errors);
}

wasmer-python (Python):

from wasmer import engine, Store, Module, Instance

store = Store()
module = Module(store, open('simple.wasm', 'rb').read())
instance = Instance(module)
result = instance.exports.sum(5, 37)

The code snippets demonstrate the different approaches:

  • wabt focuses on low-level WebAssembly operations and parsing
  • wasmer-python provides a higher-level API for running WebAssembly modules in Python

Both projects serve different purposes in the WebAssembly ecosystem, with wabt offering a broader set of tools for WebAssembly manipulation and wasmer-python providing a more streamlined runtime experience for Python developers.

18,439

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten

Pros of wasmer

  • More comprehensive WebAssembly runtime with broader language support
  • Offers a full suite of tools for WebAssembly development and deployment
  • Provides lower-level control and optimization options

Cons of wasmer

  • Steeper learning curve for Python developers
  • Requires more setup and configuration for Python-specific use cases
  • Less streamlined integration with existing Python projects

Code Comparison

wasmer (Rust):

let module = Module::new(&store, wasm_bytes)?;
let import_object = imports! {};
let instance = Instance::new(&module, &import_object)?;
let sum = instance.exports.get_function("sum")?;
let result = sum.call(&[Value::I32(1), Value::I32(2)])?;

wasmer-python (Python):

module = Module(store, wasm_bytes)
instance = Instance(module)
sum_func = instance.exports.sum
result = sum_func(1, 2)

Summary

wasmer is a more comprehensive WebAssembly runtime with broader language support and lower-level control, while wasmer-python provides a more streamlined Python-specific integration. The choice between the two depends on the specific requirements of your project and your familiarity with WebAssembly concepts.

4,064

Lucet, the Sandboxing WebAssembly Compiler.

Pros of Lucet

  • Designed for native execution, offering potentially better performance for certain use cases
  • Focuses on ahead-of-time (AOT) compilation, which can lead to faster startup times
  • Developed by the Bytecode Alliance, potentially benefiting from a broader ecosystem

Cons of Lucet

  • More limited language support compared to Wasmer-Python
  • Less flexible runtime options, as it's primarily focused on AOT compilation
  • May have a steeper learning curve for Python developers

Code Comparison

Lucet (Rust):

let module = lucet_runtime::Module::load("my_module.so")?;
let instance = module.instantiate()?;
let result = instance.run("my_function", &[])?;

Wasmer-Python (Python):

from wasmer import engine, Store, Module, Instance

module = Module(Store(), open('my_module.wasm', 'rb').read())
instance = Instance(module)
result = instance.exports.my_function()

Both examples demonstrate loading and running a WebAssembly module, but Lucet uses a native shared object file, while Wasmer-Python works directly with WebAssembly bytecode.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Wasmer logo Wasmer Python PyPI version Wasmer Python Documentation Wasmer PyPI downloads Wasmer Slack #python Channel

A complete and mature WebAssembly runtime for Python based on Wasmer.

Features

  • Secure by default. No file, network, or environment access, unless explicitly enabled.
  • Fast. Run WebAssembly at near-native speeds.
  • Compliant with latest WebAssembly Proposals (SIMD, Reference Types, Threads, ...)

Documentation: browse the detailed API documentation full of examples.

Examples and tutorials: browse the examples/ directory, it's the best place for a complete introduction!

Install

To install the wasmer Python package, and let's say the wasmer_compiler_cranelift compiler, just run those commands in your shell:

$ pip install wasmer wasmer_compiler_cranelift

Usage

from wasmer import engine, Store, Module, Instance

store = Store()

# Let's compile the module to be able to execute it!
module = Module(store, """
(module
  (type (func (param i32 i32) (result i32)))
  (func (export "sum") (type 0) (param i32) (param i32) (result i32)
    local.get 0
    local.get 1
    i32.add))
""")

# Now the module is compiled, we can instantiate it.
instance = Instance(module)

# Call the exported `sum` function.
result = instance.exports.sum(5, 37)

print(result) # 42!

And then, finally, enjoy by running:

$ python examples/appendices/simple.py

We highly recommend to read the examples/ directory, which contains a sequence of examples/tutorials. It's the best place to learn by reading examples.

Quick Introduction

The wasmer package brings the required API to execute WebAssembly modules. In a nutshell, wasmer compiles the WebAssembly module into compiled code, and then executes it. wasmer is designed to work in various environments and platforms: From nano single-board computers to large and powerful servers, including more exotic ones. To address those requirements, Wasmer provides 2 engines and 3 compilers.

Succinctly, an engine is responsible to drive the compilation and the execution of a WebAssembly module. By extension, a headless engine can only execute a WebAssembly module, i.e. a module that has previously been compiled, or compiled, serialized and deserialized. By default, the wasmer package comes with 2 headless engines:

  1. wasmer.engine.Universal, the compiled machine code lives in memory,
  2. wasmer.engine.Native, the compiled machine code lives in a shared object file (.so, .dylib, or .dll), and is natively executed.

Because wasmer does not embed compilers in its package, engines are headless, i.e. they can't compile WebAssembly module; they can only execute them. Compilers live in their own standalone packages. Let's briefly introduce them:

Compiler packageDescriptionPyPi
wasmer_compiler_singlepassSuper fast compilation times, slower execution times. Not prone to JIT-bombs. Ideal for blockchainsOn PyPi Downloads
wasmer_compiler_craneliftFast compilation times, fast execution times. Ideal for developmentOn PyPi Downloads
wasmer_compiler_llvmSlow compilation times, very fast execution times (close to native, sometimes faster). Ideal for ProductionOn PyPi Downloads

We generally recommend wasmer_compiler_cranelift for development purposes and wasmer_compiler_llvm in production.

Learn more by reading the documentation of the wasmer.engine submodule.

Supported platforms

We try to provide wheels for as many platforms and architectures as possible. For the moment, here are the supported platforms and architectures:

Platform Architecture Triple Packages
Linux amd64 x86_64-unknown-linux-gnu wasmer ✅
wasmer_compiler_singlepass ✅
wasmer_compiler_cranelift ✅
wasmer_compiler_llvm ✅
aarch64 aarch64-unknown-linux-gnu wasmer ✅
wasmer_compiler_singlepass ❌ 1
wasmer_compiler_cranelift ✅
wasmer_compiler_llvm ✅
Darwin amd64 x86_64-apple-darwin wasmer ✅
wasmer_compiler_singlepass ✅
wasmer_compiler_cranelift ✅
wasmer_compiler_llvm ✅
Windows amd64 x86_64-pc-windows-msvc wasmer ✅
wasmer_compiler_singlepass ✅
wasmer_compiler_cranelift ✅
wasmer_compiler_llvm ❌ 2

Notes:

  • 1 wasmer_compiler_singlepass does not support aarch64 for the moment
  • 2 wasmer_compiler_llvm is not packaging properly on Windows for the moment

Wheels are all built for the following Python versions:

  • Python 3.7,
  • Python 3.8.
  • Python 3.9.
  • Python 3.10,
Learn about the “fallback” py3-none-any wheel

py3-none-any.whl

A special wasmer-$(version)-py3-none-any wheel is built as a fallback. The wasmer library will be installable, but it will raise an ImportError exception saying that “Wasmer is not available on this system”.

This wheel will be installed if none matches before (learn more by reading the PEP 425, Compatibility Tags for Built Distributions).

Development

The Python extension is written in Rust, with pyo3 and maturin.

First, you need to install Rust and Python. We will not make you the affront to explain to you how to install Python (if you really need, check pyenv). For Rust though, we advise to use rustup, then:

$ rustup install stable

To set up your environment, you'll need just, and then, install the prelude of this project:

$ cargo install just
$ just --list # to learn about all the available recipes
$ just prelude

It will install pyo3 and maturin for Python and for Rust. It will also install virtualenv.

Then, simply run:

$ source .env/bin/activate
$ just build api
$ just build compiler-cranelift
$ python examples/appendices/simple.py

Testing

To build all tests you'll need LLVM 12.0 in your system. We recommend either installing prepackaged libraries with llvm.sh or building it yourself with llvmenv.

Build all the packages and run the tests:

$ just build-all
$ just test

What is WebAssembly?

Quoting the WebAssembly site:

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

About speed:

WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.

About safety:

WebAssembly describes a memory-safe, sandboxed execution environment […].

License

The entire project is under the MIT License. Please read the LICENSE file.