12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- #!/usr/bin/env python3
- import asyncio
- import time
- from multiprocessing import Manager
- from queue import Empty, Queue
- from typing import Callable, Generator
- from nicegui import app, background_tasks, run, ui
- class Worker:
- def __init__(self) -> None:
- self._queue: Queue
- self.progress: float = 0.0
- self.is_running: bool = False
- app.on_startup(self._create_queue)
- async def run(self, func: Callable[..., Generator[float, None, None]]) -> None:
- background_tasks.create(run.cpu_bound(self._run_generator, func, self._queue))
- background_tasks.create(self._consume_queue())
- @staticmethod
- def _run_generator(func: Callable[..., Generator[float, None, None]], queue: Queue) -> None:
- for progress in func():
- queue.put({'progress': progress})
- queue.put({'progress': 1.0})
- def _create_queue(self) -> None:
- self._queue = Manager().Queue()
- async def _consume_queue(self) -> None:
- self.is_running = True
- self.progress = 0.0
- while self.progress < 1.0:
- try:
- msg = self._queue.get_nowait()
- except Empty:
- await asyncio.sleep(0.1)
- continue
- self.progress = msg['progress']
- self.is_running = False
- def heavy_computation() -> Generator[float, None, None]:
- n = 50
- for i in range(n):
- time.sleep(0.1)
- yield i / n
- worker = Worker()
- @ui.page('/')
- def main_page():
- ui.button('compute', on_click=lambda: worker.run(heavy_computation))
- ui.linear_progress().props('instant-feedback') \
- .bind_value_from(worker, 'progress') \
- .bind_visibility_from(worker, 'is_running')
- ui.run()
|