🐍 PyWebView

frontend

Good to know

⭐ PyWebView lets you build a desktop GUI using HTML/CSS/JS while keeping Python as the backend. JavaScript can call Python functions (via js_api) and Python can call JS inside the window. It’s perfect for small tools, dashboards, or lightweight apps without a full web server.


Basic Setup

Creates a window, loads an HTML file, and exposes a Python API class to JavaScript.

import webview
from utils import resource_path
from api import API
 
if __name__ == "__main__":
 
    # Create an instance of your backend API
    py_api = API()
 
    # Path to your HTML frontend (works in dev + PyInstaller)
    html_path = resource_path("app/app.html")
 
    # Create the GUI window
    my_frontend_window = webview.create_window(
        "Generator",
        url=html_path,
        width=1080,
        height=900,
        js_api=py_api     # attach Python API for JS communication
    )
 
    # Called once the GUI window is ready
    def on_start():
        py_api.window = my_frontend_window
 
    # Start the frontend loop
    webview.start(on_start, debug=False)

API Class

Your custom backend that exposes Python functions to JavaScript.

class API:
 
    def __init__(self):
        self.window = None      # gets assigned on startup
 
    def my_function(self, payload_json: str) -> bool:
        print("Received from JS:", payload_json)
        return True
        
        # Anything defined here can be called from your JS frontend.

Calling Python from JavaScript

JS can call your Python API like this:

window.pywebview.api.my_function(JSON.stringify({msg: "Hi"}))
  .then(response => console.log(response));

JS receives the return value from Python as a Promise.


Calling JavaScript from Python

Python can execute JS inside the WebView window.

self.window.evaluate_js("alert('Hello from Python!')")

This makes two-way communication possible.


Useful Tips

Avoid freezing the UI

Long-running tasks should run in threads:

import threading
threading.Thread(target=self.long_task).start()

Logging to the JS console

self.window.evaluate_js("console.log('Python says hi')")