Skip to content

IPC between Python and JavaScript

pytauri implements the same IPC API as tauri. You can use it through pytauri.Commands.

This tutorial will demonstrate how to use pytauri's IPC API by rewriting the fn greet command in src-tauri/src/lib.rs in Python.

Enable pytauri ipc permission

pytauri internally implements IPC through tauri-plugin-pytauri. You need to add it to the dependencies so that you can enable its permission in tauri.

src-tauri/Cargo.toml
# ...

[dependencies]
# ...
tauri-plugin-pytauri = { version = "0.1.0-beta.0" }

Refer to https://tauri.app/security/capabilities/ to add the permission:

src-tauri/capabilities/default.json
{
    // ...
    "permissions": [
        // ...
        "pytauri:default"
    ]
}

IPC in python

install dependencies

pytauri relies on pydantic for serialization and validation, and on anyio for asyncio/trio support.

Therefore, you need to install these dependencies:

src-tauri/pyproject.toml
# ...

[project]
# ...
dependencies = [
    # ...
    "pydantic == 2.*",
    "anyio == 4.*"
]

Tip

After adding dependencies, you need to use commands like uv sync or uv pip install to synchronize your dependency environment.

add command

see concepts/ipc for more information.

src-tauri/python/__init__.py
import sys

from anyio.from_thread import start_blocking_portal
from pydantic import BaseModel
from pytauri import (
    BuilderArgs,
    Commands,
    builder_factory,
    context_factory,
)

commands: Commands = Commands()


class Person(BaseModel):
    name: str


class Greeting(BaseModel):
    message: str


@commands.command()
async def greet(body: Person) -> Greeting:
    return Greeting(
        message=f"Hello, {body.name}! You've been greeted from Python {sys.version}!"
    )

generate invoke handler for app

src-tauri/python/__init__.py
# --8<-- [start:command]

import sys

from anyio.from_thread import start_blocking_portal
from pydantic import BaseModel
from pytauri import (
    BuilderArgs,
    Commands,
    builder_factory,
    context_factory,
)

commands: Commands = Commands()


class Person(BaseModel):
    name: str


class Greeting(BaseModel):
    message: str


@commands.command()
async def greet(body: Person) -> Greeting:
    return Greeting(
        message=f"Hello, {body.name}! You've been greeted from Python {sys.version}!"
    )


# --8<-- [end:command]


def main() -> None:
    with start_blocking_portal("asyncio") as portal:  # or `trio`
        app = builder_factory().build(
            BuilderArgs(
                context=context_factory(),
                # 👇
                invoke_handler=commands.generate_handler(portal),
                # 👆
            )
        )
        app.run()

IPC in JavaScript

pytauri provides an API similar to the invoke function in @tauri-apps/api/core through tauri-plugin-pytauri-api.

First, install it: pnpm add tauri-plugin-pytauri-api.

Now, you can invoke the command from your JavaScript code:

src/main.ts
import { invoke } from "@tauri-apps/api/core";
import { pyInvoke } from "tauri-plugin-pytauri-api";
// or if tauri config `app.withGlobalTauri = true`:
//
// ```js
// const { pyInvoke } = window.__TAURI__.pytauri;
// ```

interface Greeting {
  message: string;
}

async function greet() {
  if (greetMsgEl && greetInputEl) {
    // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
    const rsGreeting = await invoke<string>("greet", {
      name: greetInputEl.value,
    });
    const pyGreeting = await pyInvoke<Greeting>("greet", {
      name: greetInputEl.value,
    });
    greetMsgEl.textContent = rsGreeting + "\n" + pyGreeting.message;
  }
}