Support hypercorn and Trio? #184
Replies: 4 comments 13 replies
-
|
Interesting. I can well imagine to add a hypercorn argument to |
Beta Was this translation helpful? Give feedback.
-
|
Has this been tried by someone? I had the luxury of being able to work exclusively with trio in the past, and got accustomed to expect clear and understandable behaviour. When I had a library like the MongoDB async driver, I was still able to work around with trio_asyncio, but got accustomed to silent swallowing of exceptions, behaviour after leaving a scope and things like that. Now, I'm a happy user of nicegui and since my libraries are all written in anyio, I decided to just run everything under asyncio, hoping to avoid some of the trio_asyncio hassles. However, now that I have an application combining three asyncio-native libaries (nicegui via uvicorn, MongoDB driver, and bleak), asyncio really showed it's teeth. I have completely unpredictable behaviour, probably some silent failure and I wish I had a trio loop. I'd be willing to do some legwork here if there is hope that this succeeds... |
Beta Was this translation helpful? Give feedback.
-
|
@burnpanck thanks for your willingness to contribute. From the FastAPI docs:
So a good first task would be a pull request which ensures that NiceGUI also uses AnyIO. |
Beta Was this translation helpful? Give feedback.
-
TL;DR: Full asyncio -> anyio Migration FeasibilityA full migration from Three Blockers
What's EasySimple primitives ( What Stays
RecommendationIf proceeding: rewrite Full technical report (click to expand)Technical Report: Full Migration from asyncio to anyioContextGitHub Discussion #184 requests migrating NiceGUI from VerdictA full migration -- removing Blocker 1: Fire-and-forget task creation (
|
| Pattern | Files | anyio replacement | Effort |
|---|---|---|---|
asyncio.sleep() |
8 files, 15 calls | anyio.sleep() -- drop-in |
Trivial |
asyncio.Event() one-shot |
6 files | anyio.Event() -- drop-in |
Trivial |
asyncio.Event() with .clear() |
4 files | Recreate event instead of clearing | Low |
asyncio.wait_for() |
6 files | anyio.fail_after() context manager |
Low |
asyncio.gather() |
4 files | anyio.create_task_group() |
Medium |
asyncio.Future |
1 file | anyio.Event() + result holder |
Low |
asyncio.CancelledError |
8 files | anyio.get_cancelled_exc_class() (verbose but works) |
Low |
asyncio.Task type hints |
10 files | Needs task wrapper type or TYPE_CHECKING |
Medium |
isinstance(x, asyncio.Task) |
4 files | Custom task wrapper or duck typing | Medium |
asyncio.iscoroutine() |
2 files | inspect.iscoroutine() |
Trivial |
loop.run_in_executor(thread_pool) |
1 file | anyio.to_thread.run_sync() |
Medium |
loop.run_in_executor(process_pool) |
1 file | No good anyio equivalent (custom executor + BrokenProcessPool recovery) | Keeps asyncio |
Effort Estimate for Full Migration
| Component | Effort | Risk |
|---|---|---|
| Simple primitives (sleep, Event, wait_for, gather) | Low | Low |
| Resettable Events (dialog, outbox, client) | Medium | Medium |
background_tasks.py rewrite (task nursery + queue) |
High | High |
page.py task racing rewrite |
High | High |
slot.py manual task tracking |
Medium | Medium |
run.py io_bound -> anyio.to_thread |
Medium | Medium |
Replace all asyncio.CancelledError |
Low | Low |
Replace asyncio.Task types everywhere |
Medium | Medium |
| Total | ~2-3 days + extensive testing | High overall |
Recommendation
The full migration touches NiceGUI's deepest infrastructure -- how it manages async tasks, how pages render, and how slot stacks track UI hierarchy. The high-risk components (background_tasks.py, page.py) are among the most critical and hardest-to-test parts of the framework.
If you want to proceed with a full migration, the implementation order should be:
- Rewrite
background_tasks.py(queue-based task nursery) -- everything else depends on this - Update
slot.pyto use manual task tracking from the nursery - Rewrite
page.pytask racing with cancel scopes - Migrate all simple primitives (sleep, Event, wait_for, gather, Future)
- Replace
asyncio.CancelledErrorwithanyio.get_cancelled_exc_class() - Migrate
run.pyio_bound toanyio.to_thread.run_sync() - Clean up remaining
asyncio.Tasktype usage - Note:
run.pycpu_bound keeps asyncio (process pool management)
If you want to defer the risky parts, the simple primitives (sleep, Event, wait_for, gather) can be migrated independently. Files that also need asyncio for Task/CancelledError would keep both imports.
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I would like to use NiceGUI with Trio instead of asyncio. This means implementing hypercorn in addition to uvicorn, because the latter does not plan to support Trio
Beta Was this translation helpful? Give feedback.
All reactions