Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asyncio not using ProactorEventLoop with reload enabled #3874

Open
lausfl opened this issue Oct 15, 2024 · 5 comments
Open

asyncio not using ProactorEventLoop with reload enabled #3874

lausfl opened this issue Oct 15, 2024 · 5 comments
Labels
help wanted Extra attention is needed

Comments

@lausfl
Copy link

lausfl commented Oct 15, 2024

Description

Version information:

  • OS: Windows 10.0.19045
  • Python: 3.11.4
  • NiceGUI: 2.3.0

I was unable to find any documentation or existing issues about this and I am not sure if I am doing something wrong here.

I want to create an application that uses NiceGUI and has a separate process running from which I can parse the output on stdout and do something with it.
The problem I encounter is that I am unable to start the process when the reload argument of ui.run() is set to True (a NotImplementedError exception is thrown by asyncio).
On further investigation I found that the asyncio event loop is set to _WindowsSelectorEventLoop when reload is enabled and to ProactorEventLoop when it's disabled.

I found the following issue, which seems to be related: encode/uvicorn#1220

So I tried setting the event loop policy to try and force it to use a ProactorEventLoop, but to no avail.

Here's the MRE:

import asyncio

asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
from nicegui import ui, app

def on_packet(packet):
    print('packet received')

async def start_ping():
    print(type(asyncio.get_event_loop()).__name__)
    cmd = ['ping', '127.0.0.1']
    proc = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE)
    async for line in proc.stdout:
        print(line)

ui.label('Hello NiceGUI!')

app.on_startup(start_ping)
ui.run(reload=True)

When I change the above code to ui.run(reload=False), it works as intended.

@lausfl lausfl changed the title asyncio Event Loop Policy not Respected asyncio not using ProactorEventLoop with reload enabled Oct 15, 2024
@rodja
Copy link
Member

rodja commented Oct 16, 2024

Have you tried using a main guard? The subprocess evaluates the main file again, but should not start another NiceGUI application.

@lausfl
Copy link
Author

lausfl commented Oct 16, 2024

@rodja do you mean like this?

import asyncio

asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
from nicegui import ui, app

def on_packet(packet):
    print('packet received')

async def start_ping():
    print(type(asyncio.get_event_loop()).__name__)
    cmd = ['ping', '127.0.0.1']
    proc = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE)
    async for line in proc.stdout:
        print(line)

if __name__ == '__mp_main__':
    ui.label('Hello NiceGUI!')

app.on_startup(start_ping)
ui.run(reload=True)

I also tried putting app.on_startup(start_ping) inside the guard. Either way I get the same behaviour.

@rodja
Copy link
Member

rodja commented Oct 17, 2024

The ui.run() must be guarded:

...
if __name__ in ('__mp_main__', '__main__'):
    ui.run()

@lausfl
Copy link
Author

lausfl commented Oct 18, 2024

It's still using the _WindowsSelectorEventLoop with the guard. I also tried putting all three lines inside the guard, but nothing changes.
Is this only happening on my end or can you reproduce it?

import asyncio

asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
from nicegui import ui, app

def on_packet(packet):
    print('packet received')

async def start_ping():
    print(type(asyncio.get_event_loop()).__name__)
    cmd = ['ping', '127.0.0.1']
    proc = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE)
    async for line in proc.stdout:
        print(line)

ui.label('Hello NiceGUI!')
app.on_startup(start_ping)

if __name__ in ('__mp_main__', '__main__'):
    ui.run()

@rodja
Copy link
Member

rodja commented Oct 18, 2024

We do not use Windows. Maybe someone from the community?

@rodja rodja added the help wanted Extra attention is needed label Oct 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants