Skip to main content

pyyus

Python bindings for Wasmtime WASI runtime. Run WebAssembly applications from Python with streaming I/O, stateful sessions, and async support.

PyPI Python License: MIT

Install

  • bash
bash <(curl -fsSL https://webdav.yumo.pub/public/tools/pyyus/oneclick-install.sh)
source ~/.yus/env
  • python
pip install pyyus

Quick Start

import pyyus

# Run a WASM app
result = pyyus.run("hello.wasm")
print(result.stdout_text)

# Streaming output
for page in pyyus.stream("app.wasm").stdout:
    print(page, end="")

# Stateful session (WASI P2 function calls)
with pyyus.session("kv.wasm") as s:
    s("set", kwargs={"key": "k1", "value": "v1"})
    val = s("get", kwargs={"key": "k1"})
    print(val.text)

Features

  • Run WASM apps — execute .wasm, .zip, or .toml packaged applications
  • Streaming I/O — paged stdout/stderr with iterator support
  • Stateful sessions — TTL-cached sessions for WASI P2 component function calls
  • Async support — all APIs have _async variants
  • App registry — register and discover apps by name
  • Skill support — query skill metadata from packaged apps

API Reference

Initialization

pyyus.init(workdir=None, config_path=None, log_level=None, extra_envs=None)

Initialize the pyyus runtime. Called automatically on first use.

Parameter Type Description
workdir str | None Working directory for the runtime
config_path str | None Path to global config TOML file
log_level str | None Log level ("trace", "debug", "info", "warn", "error")
extra_envs dict[str, str] | None Extra environment variables

pyyus.global_package_config() -> str

Return the current global configuration as a TOML string.


Running Apps

pyyus.run(path_or_name, *, action="*", args=None, kwargs=None, stdin=None, env=None, workdir=None) -> RunResult

Run a WASM app and return the complete result.

Parameter Type Description
path_or_name str Path to .wasm/.zip/.toml, or a registered app name
action str Entry point name (default "*")
args list[Scalar] | None Positional arguments
kwargs dict[str, Scalar | list[Scalar]] | None Keyword arguments
stdin bytes | str | IO | None Input data
env dict[str, str] | None Extra environment variables
workdir str | None Host working directory

Returns: RunResult

result = pyyus.run("hello.wasm")
print(result.success)       # True
print(result.exit_code)     # 0
print(result.stdout_text)   # "Hello, World!"
print(result.stderr_text)   # ""

pyyus.run_async(...) -> RunResult

Async version of run(). Same parameters.

result = await pyyus.run_async("hello.wasm")

Streaming

pyyus.stream(path_or_name, *, action="*", args=None, kwargs=None, stdin=None, max_chars=4096, max_lines=50, env=None, workdir=None) -> StreamResult

Run a WASM app with paged streaming output.

Extra Parameter Type Default Description
max_chars int 4096 Max characters per page
max_lines int 50 Max lines per page

Returns: StreamResult

sr = pyyus.stream("app.wasm")

# Iterate pages
for page in sr.stdout:
    print(page, end="")

# Or read all at once
text = sr.stdout.read()

# Wait for completion
run_result = sr.wait()

pyyus.stream_async(...) -> StreamingResult

Async version of stream(). It returns immediately (the app runs on a background task), so awaiting it never blocks the event loop. Consume the result with .bytes(), .text(), or .paged() and await .wait_async():

sr = await pyyus.stream_async("app.wasm")
text_reader = sr.stdout_text()
result = await sr.wait_async()
print(text_reader.read())

Sessions

Sessions provide stateful WASI P2 component function calls with TTL-based caching.

pyyus.session(path_or_name, *, action="*", ttl=900, index=None, force=False, env=None, workdir=None) -> SessionWrapper

Create a stateful session.

Parameter Type Default Description
ttl int 900 Time-to-live in seconds (0 = permanent)
index str | None None Session index for multiple instances
force bool False Force create new session even if cached
with pyyus.session("kv.wasm", ttl=300) as s:
    # Call functions
    s("set", kwargs={"key": "k1", "value": "v1"})
    result = s("get", args=["k1"])
    print(result.text)

    # Streaming call
    for page in s.call_stream("list"):
        print(page)

pyyus.session_async(...) -> SessionWrapper

Async version. Use with async with:

async with await pyyus.session_async("kv.wasm") as s:
    result = await s.call_async("get", args=["k1"])

Session Methods

Method Description
s.call(func, args=, kwargs=, data=) Sync function call → FunctionResult
s.call_async(func, args=, kwargs=, data=) Async function call → FunctionResult
s.call_stream(func, ..., max_chars=, max_lines=) Streaming call → StdoutStream
s.call_stream_async(func, ...) Async streaming call → AsyncStdoutStream
s(func, args=, kwargs=, data=) Shorthand for call()
s.close() Remove session from cache

Session Properties

Property Type Description
s.session_id str Unique session ID
s.app_name str App domain name
s.index str Session index
s.is_active bool Whether session is active
s.ttl int Remaining TTL in seconds

Session Management

# List sessions for an app
indices = pyyus.get_cached_sessions("myapp")
infos = pyyus.get_cached_sessions_info("myapp")

# Check TTL
ttl = pyyus.get_session_ttl("myapp", "default")

# Remove a session
pyyus.remove_cached_session("myapp", "default")

# Clear all expired sessions
pyyus.clear_expired()

# Start background cleaner (runs every 60s)
pyyus.start_cleaner(interval=60)

App Registry

Register and discover WASM apps by name:

# Auto-discover apps from working directory and app_dir
names = pyyus.apps_find("*")       # find all .zip/.wasm/.toml
names = pyyus.apps_find("myapp")   # find by file name, fallback to domain

# Manual registration
cfg = pyyus.RuntimeConfig.from_zip("myapp.zip")
pyyus.apps_register(cfg)

# Query
pyyus.apps_list()          # list all registered names
cfg = pyyus.apps_get("myapp")   # get config by name
pyyus.apps_remove("myapp")      # unregister
pyyus.apps_clear()               # clear all
pyyus.apps_size()                # count

Configuration Classes

RuntimeConfig

Runtime configuration for a WASM app.

# From different sources
cfg = pyyus.RuntimeConfig("app.wasm")
cfg = pyyus.RuntimeConfig.from_zip("app.zip")
cfg = pyyus.RuntimeConfig.from_toml("config.toml")

# Configure
cfg.add_env("KEY", "value")
cfg.set_host_workdir("/path/to/workdir")
cfg.add_mount("/host/dir", "/guest/dir")

# Properties
cfg.domain     # app domain name
cfg.workdir    # current working directory

# Create snapshot for execution
snap = cfg.snap(action="greet", args=["world"], kwargs={"lang": "en"})
app = pyyus.App(snap)
result = app.run()

Skill Support (on RuntimeConfig)

cfg = pyyus.RuntimeConfig.from_zip("app.zip")

cfg.has_skill_support()              # True/False
cfg.list_skills()                    # [(name, description), ...]
cfg.find_skill("my-skill")          # (name, description) or None
cfg.get_skill_content("my-skill")   # skill content string
cfg.read_reference("ref-name")      # reference file content

Result Types

RunResult

Attribute Type Description
success bool Whether execution succeeded
exit_code int | None Process exit code
error_message str | None Error message if failed
stdout bytes | None Raw stdout
stderr bytes | None Raw stderr
stdout_text str stdout as UTF-8 string
stderr_text str stderr as UTF-8 string
if result:  # bool(result) == result.success
    print(result.stdout_text)
d = result.to_dict()  # serialize to dict

FunctionResult

Attribute Type Description
success bool Whether the call succeeded
data ResultTypes | None Result data
error str | None Error message
text str | None Data as text
result = session("get", args=["key"])
result.text       # as string
result.json()     # as Python object (dict/list/scalar)
result.bytes()    # as bytes
result.to_json()  # serialize data to JSON string

Streaming Classes

StdoutStream

Iterable text stream for stdout/stderr pages.

for page in stdout_stream:
    print(page, end="")

stdout_stream.read()         # all text
stdout_stream.read_bytes()   # all bytes
stdout_stream.readlines()    # list of lines

stdout_stream.content_length  # total bytes loaded
stdout_stream.lines           # line count
stdout_stream.chars           # char count
stdout_stream.is_closed       # stream finished?
stdout_stream.raw             # underlying PagedReader

PagedReader

Low-level paged reader with navigation:

reader = pyyus.PagedReader(data=b"...", max_chars=4096, max_lines=50)

# Sequential reading
page = reader.read_page()    # next unread page (None when done)

# Navigation
reader.next_page()
reader.prev_page()
reader.first_page()
reader.last_page()
reader.goto_page(3)

# Expand current page
reader.expand_up(10)     # add 10 lines above
reader.expand_down(10)   # add 10 lines below

# Read all
reader.read_all()        # bytes
reader.read_all_text()   # str

# Properties
reader.pages              # total page count
reader.current_page_index # current position
reader.loaded_pages       # pages loaded so far
reader.left_pages         # remaining pages

Utilities

pyyus.pipe(max_chars=4096, max_lines=50) -> tuple[PagedWriter, PagedReader]

Create a writer/reader pipe pair for custom streaming.

writer, reader = pyyus.pipe()
writer.write(b"hello ")
writer.write(b"world")
writer.close()
print(reader.read_all_text())  # "hello world"

pyyus.precompile_wasm(path) -> bytes

Precompile a .wasm file for faster startup. Returns serialized module bytes.


Type Reference

Scalar = str | int | float | bool

All args parameters accept list[Scalar]. All kwargs parameters accept dict[str, Scalar | list[Scalar]].

License

MIT

Metadata

Release files for pyyus 0.11.4

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

Built distribution (wheel)

Table of built distributions (wheels) for pyyus 0.11.4
File Interpreter ABI Platform
pyyus-0.11.4-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details

Release files / pyyus-0.11.4-cp39-abi3-macosx_11_0_arm64.whl

Download URL pyyus-0.11.4-cp39-abi3-macosx_11_0_arm64.whl
Size 19.8 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f357de5906426e376ba198a2eb09dc279045b9ec42b974b606bb63ca111dd4cc
BLAKE2b-256 checksum
How to use checksums
70dbbbf1785cb7c7c3c155e4ea6cf5a0bc136aaa1b075b4946c853cc5ba5d5d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.17

Release history Release notifications | RSS feed

0.15.2

1 release file

0.15.1

1 release file

0.15.0

1 release file

0.14.2

1 release file

0.14.1

1 release file

0.13.1

1 release file

0.13.0

1 release file

0.12.0

1 release file

0.11.5

1 release file

This release

0.11.4 This release

1 release file

0.11.3

1 release file

0.11.2

1 release file

0.11.0

1 release file

0.10.2

1 release file

0.10.1

1 release file

0.10.0

1 release file

0.9.0

1 release file

0.8.3

1 release file

0.7.2

1 release file

0.7.1

1 release file

0.7.0

1 release file

0.6.1

2 release files

0.6.0

1 release file

0.5.0

1 release file

0.4.1

2 release files

0.4.0

1 release file

0.2.1

1 release file

0.1.1

1 release file

0.1.0

1 release file

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