Skip to content

Instantly share code, notes, and snippets.

@eli-kha
Created March 11, 2023 20:36
Show Gist options
  • Save eli-kha/06a47bfdf1e50f4cdfc3f43a199a6d2d to your computer and use it in GitHub Desktop.
Save eli-kha/06a47bfdf1e50f4cdfc3f43a199a6d2d to your computer and use it in GitHub Desktop.
A small demo of using pywebview with NiceGUI based on wrapping both Unicorn.Server and webview in processes.
#!/usr/bin/env python3
import multiprocessing
import tempfile
from fastapi import FastAPI
from uvicorn import Config, Server
import webview
from nicegui import ui
class UvicornServer(multiprocessing.Process):
def __init__(self, config: Config):
super().__init__()
self.server = Server(config=config)
self.config = config
def stop(self):
self.terminate()
def run(self, *args, **kwargs):
self.server.run()
def start_window(pipe_send, url_to_load):
def on_closed():
pipe_send.send('closed')
win = webview.create_window('Demo', url=url_to_load)
win.events.closed += on_closed
webview.start(storage_path=tempfile.mkdtemp())
app = FastAPI()
@app.get('/')
def read_root():
return {'Hello': 'World'}
@ui.page('/show')
def show():
ui.image('https://picsum.photos/id/377/640/360')
ui.run_with(app)
if __name__ == '__main__':
server_ip = "127.0.0.1"
server_port = 8080
conn_recv, conn_send = multiprocessing.Pipe()
windowsp = multiprocessing.Process(target=start_window, args=(conn_send, f'http://{server_ip}:{server_port}/show'))
windowsp.start()
config = Config("main:app", host=server_ip, port=server_port, log_level="debug")
instance = UvicornServer(config=config)
instance.start()
window_status = ''
while 'closed' not in window_status:
# get a unit of work
window_status = conn_recv.recv()
# report
print(f'got {window_status}', flush=True)
instance.stop()
@J3ronimo
Copy link

Great stuff, thank you!

In NiceGUI they have ui.run_with(app) and ui.run(native=True). Running 2 separate processes like you did so far seems the only way to combine these.

@eli-kha
Copy link
Author

eli-kha commented Jan 25, 2025

@J3ronimo thanks.
BTW this gist was written before run_with and native=True existed and this code is the basis for the native mode (you can look it up in the discussions of the nicegui repo).

AFAIK native mode uses multiprocessing with a better implementation than this POC gist :)

@J3ronimo
Copy link

I'll have to check that out. I want to run_with an own FastAPI app in native mode, but this gist so far was the only code I found that achieves that. Dont get me wrong, this could be a lot easier. But it's not there yet in NiceGUI directly as far as I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment