CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pyodide

Python distribution for the browser and Node.js based on WebAssembly that enables running Python code with full JavaScript interoperability

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

ffi.mddocs/

Foreign Function Interface (FFI)

Pyodide's Foreign Function Interface provides seamless interoperability between JavaScript and Python, enabling automatic type conversion and proxy objects for cross-language operation.

FFI Module

The FFI module exports type classes and utilities for working with Python objects from JavaScript.

import { ffi } from "pyodide/ffi";

const ffi: {
  PyProxy: typeof PyProxy;
  PyProxyWithLength: typeof PyProxyWithLength;
  PyProxyWithGet: typeof PyProxyWithGet;
  PyProxyWithSet: typeof PyProxyWithSet;
  PyProxyWithHas: typeof PyProxyWithHas;
  PyDict: typeof PyDict;
  PyIterable: typeof PyIterable;
  PyAsyncIterable: typeof PyAsyncIterable;
  PyIterator: typeof PyIterator;
  PyAsyncIterator: typeof PyAsyncIterator;
  PyGenerator: typeof PyGenerator;
  PyAsyncGenerator: typeof PyAsyncGenerator;
  PyAwaitable: typeof PyAwaitable;
  PyCallable: typeof PyCallable;
  PyBuffer: typeof PyBuffer;
  PyBufferView: typeof PyBufferView;
  PySequence: typeof PySequence;
  PyMutableSequence: typeof PyMutableSequence;
  PythonError: typeof PythonError;
};

Core FFI Types

PyProxy

Base proxy type for all Python objects accessible from JavaScript.

interface PyProxy {
  /** Check if object has been destroyed */
  readonly destroyed: boolean;
  /** Destroy the proxy and release Python reference */
  destroy(): void;
  /** Convert to JavaScript object */
  toJs(options?: ConversionOptions): any;
  /** Create a copy with new conversion options */
  copy(): PyProxy;
  /** Get string representation (str() in Python) */
  toString(): string;
  /** Get detailed representation (repr() in Python) */
  supportsLength(): this is PyProxyWithLength;
  supportsGet(): this is PyProxyWithGet;
  supportsSet(): this is PyProxyWithSet;
  supportsHas(): this is PyProxyWithHas;
}

PyProxyWithLength

Proxy for Python objects that support len().

interface PyProxyWithLength extends PyProxy {
  readonly length: number;
}

PyProxyWithGet

Proxy for Python objects that support item access (obj[key]).

interface PyProxyWithGet extends PyProxy {
  get(key: any): any;
}

PyProxyWithSet

Proxy for Python objects that support item assignment (obj[key] = value).

interface PyProxyWithSet extends PyProxy {
  set(key: any, value: any): void;
  delete(key: any): void;
}

PyProxyWithHas

Proxy for Python objects that support membership testing (key in obj).

interface PyProxyWithHas extends PyProxy {
  has(key: any): boolean;
}

Collection Types

PyDict

Proxy for Python dictionaries with JavaScript Map-like interface.

interface PyDict extends PyProxy {
  get(key: any): any;
  set(key: any, value: any): void;
  delete(key: any): boolean;
  has(key: any): boolean;
  keys(): PyProxy;
  values(): PyProxy;
  items(): PyProxy;
}

Usage Example:

// Create Python dict and work with it
const pythonDict = pyodide.runPython(`
    {'name': 'Alice', 'age': 30, 'city': 'New York'}
`);

console.log(pythonDict.get('name')); // 'Alice'
pythonDict.set('age', 31);
console.log(pythonDict.has('city')); // true
pythonDict.delete('city');

// Convert to JavaScript object
const jsObject = pythonDict.toJs();
console.log(jsObject); // {name: 'Alice', age: 31}

PySequence

Proxy for Python sequences (lists, tuples, strings) with array-like interface.

interface PySequence extends PyProxy {
  readonly length: number;
  get(index: number): any;
  slice(start?: number, stop?: number): PySequence;
}

PyMutableSequence

Proxy for mutable Python sequences (lists) with modification capabilities.

interface PyMutableSequence extends PySequence {
  set(index: number, value: any): void;
  delete(index: number): void;
  append(value: any): void;
  extend(iterable: any): void;
  insert(index: number, value: any): void;
  pop(index?: number): any;
  reverse(): void;
  sort(compare?: (a: any, b: any) => number): void;
}

Usage Example:

// Create Python list and manipulate it
const pythonList = pyodide.runPython('[1, 2, 3, 4, 5]');

console.log(pythonList.length); // 5
console.log(pythonList.get(0)); // 1

pythonList.append(6);
pythonList.insert(0, 0);
console.log(pythonList.toJs()); // [0, 1, 2, 3, 4, 5, 6]

const sliced = pythonList.slice(1, 4);
console.log(sliced.toJs()); // [1, 2, 3]

Async and Iterator Types

PyIterable

Proxy for Python iterable objects.

interface PyIterable extends PyProxy {
  [Symbol.iterator](): Iterator<any>;
}

PyAsyncIterable

Proxy for Python async iterable objects.

interface PyAsyncIterable extends PyProxy {
  [Symbol.asyncIterator](): AsyncIterator<any>;
}

PyIterator

Proxy for Python iterator objects.

interface PyIterator extends PyProxy {
  next(): IteratorResult<any>;
  [Symbol.iterator](): PyIterator;
}

PyAsyncIterator

Proxy for Python async iterator objects.

interface PyAsyncIterator extends PyProxy {
  next(): Promise<IteratorResult<any>>;
  [Symbol.asyncIterator](): PyAsyncIterator;
}

Function and Callable Types

PyCallable

Proxy for Python callable objects (functions, methods, classes).

interface PyCallable extends PyProxy {
  (...args: any[]): any;
  callKwargs(...args: any[], kwargs?: { [key: string]: any }): any;
  apply(thisArg: any, args: any[]): any;
  call(thisArg: any, ...args: any[]): any;
}

Usage Example:

// Call Python functions from JavaScript
const mathFunc = pyodide.runPython(`
    def calculate(x, y, operation='add'):
        if operation == 'add':
            return x + y
        elif operation == 'multiply':
            return x * y
        return 0
    calculate
`);

// Call with positional arguments
const result1 = mathFunc(5, 3);
console.log(result1); // 8

// Call with keyword arguments
const result2 = mathFunc.callKwargs(5, 3, { operation: 'multiply' });
console.log(result2); // 15

PyGenerator

Proxy for Python generator objects.

interface PyGenerator extends PyProxy {
  next(value?: any): IteratorResult<any>;
  return(value?: any): IteratorResult<any>;
  throw(error?: any): IteratorResult<any>;
  [Symbol.iterator](): PyGenerator;
}

PyAsyncGenerator

Proxy for Python async generator objects.

interface PyAsyncGenerator extends PyProxy {
  next(value?: any): Promise<IteratorResult<any>>;
  return(value?: any): Promise<IteratorResult<any>>;
  throw(error?: any): Promise<IteratorResult<any>>;
  [Symbol.asyncIterator](): PyAsyncGenerator;
}

PyAwaitable

Proxy for Python awaitable objects (coroutines, futures).

interface PyAwaitable extends PyProxy {
  then<TResult1 = any, TResult2 = never>(
    onfulfilled?: (value: any) => TResult1 | PromiseLike<TResult1>,
    onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>
  ): Promise<TResult1 | TResult2>;
}

Usage Example:

// Work with async Python functions
const asyncFunc = pyodide.runPython(`
    import asyncio
    
    async def fetch_data():
        await asyncio.sleep(0.1)
        return "Data fetched!"
    
    fetch_data
`);

// Await Python coroutine
const result = await asyncFunc();
console.log(result); // "Data fetched!"

Buffer Types

PyBuffer

Proxy for Python buffer protocol objects.

interface PyBuffer extends PyProxy {
  readonly byteLength: number;
  readonly format: string;
  readonly itemsize: number;
  readonly ndim: number;
  readonly readonly: boolean;
  readonly shape: number[] | null;
  readonly strides: number[] | null;
  getBuffer(order?: 'C' | 'F'): ArrayBuffer;
}

PyBufferView

A view into a Python buffer as a typed array.

interface PyBufferView extends PyProxy {
  readonly buffer: ArrayBuffer;
  readonly byteLength: number;
  readonly byteOffset: number;
  readonly length: number;
  readonly BYTES_PER_ELEMENT: number;
}

Usage Example:

// Work with NumPy arrays through buffer interface
await pyodide.loadPackage('numpy');
const npArray = pyodide.runPython(`
    import numpy as np
    np.array([1, 2, 3, 4, 5], dtype=np.float32)
`);

console.log('Array shape:', npArray.shape);
console.log('Array dtype:', npArray.format);

// Get buffer view
const buffer = npArray.getBuffer();
const float32View = new Float32Array(buffer);
console.log('JavaScript view:', float32View); // [1, 2, 3, 4, 5]

Error Handling

PythonError

JavaScript representation of Python exceptions.

interface PythonError extends Error {
  readonly type: string;
  readonly value: PyProxy;
  readonly traceback: PyProxy;
}

Usage Example:

import { ffi } from "pyodide/ffi";

try {
  pyodide.runPython(`
    raise ValueError("Something went wrong!")
  `);
} catch (error) {
  if (error instanceof ffi.PythonError) {
    console.log('Python error type:', error.type);
    console.log('Python error message:', error.message);
    console.log('Python traceback:', error.traceback.toString());
  }
}

Type Conversion Options

interface ConversionOptions {
  /** Maximum depth for recursive conversion */
  depth?: number;
  /** Custom converter for objects without default conversion */
  defaultConverter?: (
    value: any,
    converter: (value: any) => any,
    cacheConversion: (input: any, output: any) => void
  ) => any;
  /** Convert Python dictionaries to JavaScript Maps */
  dictConverter?: (
    items: Iterable<[key: string, value: any]>
  ) => Map<string, any> | object;
}

Runtime Type Checking

Use FFI classes for runtime type checking:

import { ffi } from "pyodide/ffi";

function processData(pythonObject) {
  if (pythonObject instanceof ffi.PyDict) {
    console.log('Processing Python dictionary...');
    for (const [key, value] of pythonObject.items()) {
      console.log(`${key}: ${value}`);
    }
  } else if (pythonObject instanceof ffi.PySequence) {
    console.log('Processing Python sequence...');
    for (let i = 0; i < pythonObject.length; i++) {
      console.log(`Item ${i}: ${pythonObject.get(i)}`);
    }
  } else if (pythonObject instanceof ffi.PyCallable) {
    console.log('Processing Python function...');
    const result = pythonObject();
    console.log('Function result:', result);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-pyodide

docs

advanced-features.md

code-execution.md

ffi.md

file-system.md

index.md

interoperability.md

io-streams.md

package-management.md

runtime-loading.md

tile.json