Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use tauri app and python script as a back end

i wanted to know how to use python script with tauri app, i tried a few things but failed i try to take an input from the user using html tag then want to pass it to python and then after the python code does the adding wanted to display the result back in the html page, i got confused how to communicate the two of them(python and javascript) i saved my python script in the same directory as the html but when i click the button there is not response,

this is my python script

    num1 = int(sys.argv[1])
    num2 = int(sys.argv[2])
    result = num1 + num2
    print(str(result))

and this is the html part

<html>
<head>
  <meta charset="UTF-8">
  <title>My Tauri App</title>
</head>
<body>
  <label for="num1">Enter number 1:</label>
  <input type="number" id="num1">

  <label for="num2">Enter number 2:</label>
  <input type="number" id="num2">

  <button id="addBtn">Add Numbers</button>

  <div id="result"></div>

  <script>
    const { spawn } = require('child_process');

    const addBtn = document.getElementById('addBtn');
    const num1Input = document.getElementById('num1');
    const num2Input = document.getElementById('num2');
    const resultDiv = document.getElementById('result');

    addBtn.addEventListener('click', () => {
      const num1 = parseInt(num1Input.value);
      const num2 = parseInt(num2Input.value);

      const python = spawn('python', ['add_numbers.py', num1.toString(), num2.toString()]);

      python.stdout.on('data', data => {
        const result = data.toString().trim();
        resultDiv.textContent = `Result: ${result}`;
      });

      python.stderr.on('data', error => {
        console.error(error.toString());
      });
    });
  </script>
</body>
</html>

i saved my python script in the same directory as the html but when i click the button there is not response,

like image 279
Faiza Abdella Avatar asked May 20 '26 21:05

Faiza Abdella


2 Answers

I am building an app utilising Tauri, Python and React. You can spawn the python instance as a "sidecar" as they're called in the Tauri platform.

Tauri offers several ways to communicate between tauri-sidecar & tauri-react frontend.

You may find documentation on embedding binaries as a sidecar to the Tauri app here; https://tauri.app/v1/guides/building/sidecar/

Once you build your python script into a standalone executable using PyInstaller, you can place it in your project folder, and then initiate that as a sidecar executable.

Once you initiate the sidecar; at the very simplest, you can listen to the stdout of the python executable, from the tauri app.

    let (mut rx, mut child) = Command::new_sidecar("pythonexecutablename")
    .expect("failed to create `pythonexecutablename` binary command")
    .spawn()
    .expect("Failed to spawn sidecar");

tauri::async_runtime::spawn(async move {
    let main_window = app.get_window("main").unwrap();
    while let Some(event) = rx.recv().await {
        if let CommandEvent::Stdout(line) = event {
            println!("Output from sidecar command: {}", line);
            if line.contains("MESSAGE:STARTED") {
                main_window
                    .emit("sidecar-ready", Some(()))
                    .expect("failed to emit event");
            }
            main_window
                .emit("message", Some(format!("'{}'", line)))
                .expect("failed to emit event");
            child.write("message from Rust\n".as_bytes()).unwrap();
        }
    }
});

In a similar fashion, you can also communicate between the React app and the Tauri app as well.

import { emit, listen } from "@tauri-apps/api/event";
import { invoke } from "@tauri-apps/api/tauri";
invoke("is_app_ready").then((message) => {
  console.log("RN - tauri app responded : ", message);
  if (message === true) {
    // Call listenUp when sidecar is ready
    initiateListening();
  } else {
    const handler = listen("sidecar-ready", (event) => {
      initiateListening();
    });
  }
});

I personally wouldn't depend heavily on the specialised communication interface provided by the Tauri API, because you never know when you may switch your UI layer, or have another user interface for the backend, so once I complete the initialisation and initial handshake, I start an SSE endpoint (server-side sent events) directly to the python backend. Then listen to that from the react app.

like image 153
Ahmet Yildirim Avatar answered May 22 '26 10:05

Ahmet Yildirim


There is also now tauri-plugin-python to run python code in the tauri backend. This doesn't spawn a new python process on each click but creates a RustPython / PyO3 python interpreter in tauri, which then parses and executes the python code during runtime. The python process doesn't end on each click, so you can also use persistent globals in your python code.

This mostly simplifies python usage in tauri. You don't need to touch any rust code anymore, you just need to have rust&npm installed so you can compile your tauri app. To create a new tauri project using python, you can just use the tauri cli to add the python interpreter.

npm create tauri-app@latest #make sure you use tauri 2
cd tauri-app
npx @tauri-apps/cli add python
# modify src/index.html and add src-tauri/src-python/main.py
npm install
npm run tauri dev
<!-- src/index.html -->
<html>

<head>
  <meta charset="UTF-8">
  <title>My Tauri App</title>
</head>

<body>
  <label for="num1">Enter number 1:</label>
  <input type="number" id="num1">

  <label for="num2">Enter number 2:</label>
  <input type="number" id="num2">

  <button id="addBtn">Add Numbers</button>

  <div id="result"></div>

  <script>
    // this should be moved to a main.js file
    const tauri = window.__TAURI__;
    let num1Input;
    let num2Input;
    let resultDiv;

    async function add_numbers() {
      let num1 = parseInt(num1Input.value);
      let num2 = parseInt(num2Input.value);
      resultDiv.textContent = `Result: ` + await tauri.python.callFunction("add_numbers", [num1, num2]);
    }

    window.addEventListener("DOMContentLoaded", () => {
      num1Input = document.querySelector("#num1");
      num2Input = document.querySelector("#num2");
      resultDiv = document.querySelector("#result");
      document.querySelector("#addBtn").addEventListener("click", (e) => {
        add_numbers();
        e.preventDefault();
      });
    });
  </script>
</body>

</html>
# src-tauri/src-python/main.py
_tauri_plugin_functions = ["add_numbers"] # allow function(s) to be callable from UI
print("initialized python")
def add_numbers(num1, num2):
    result = str(num1 + num2)
    print(result)
    return "from python: " + result

Disclaimer: I am the author of the python plugin.

like image 39
Marco Avatar answered May 22 '26 11:05

Marco