nicegui icon indicating copy to clipboard operation
nicegui copied to clipboard

`asyncio.create_subprocess_exec` does not work on windows

Open wielandb opened this issue 1 year ago • 8 comments

Transferred from #454

One example file uses asyncio and its create_subprocess_exec function. If run on windows, this function raises a NotImplementedError, because, as far as I can tell, it's not available on windows.

It would be interesting to research if an alternative solution could be found to make the example file run on all platforms.

wielandb avatar Mar 09 '23 13:03 wielandb

I also have this problem with script executor example.

Error is: in _make_subprocess_transport raise NotImplementedError

spehj avatar Mar 10 '23 15:03 spehj

I found a workaround using this code in main.py of the script executor example:

import subprocess

sync def run_command(command: str) -> None:
    '''Run a command in the background and display the output in the pre-created dialog.'''
    dialog.open()
    result.content = ''
    process = subprocess.Popen(
        command,
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        cwd=os.path.dirname(os.path.abspath(__file__))
    )
    # NOTE we need to read the output in chunks, otherwise the process will block
    output = ''
    while True:
        new = process.stdout.read(4096)
        if not new:
            break
        output += new.decode()
        # NOTE the content of the markdown element is replaced every time we have new output
        result.content = f'```\n{output}\n```

spehj avatar Mar 11 '23 12:03 spehj

Thanks for the code, @spehj. Unfortunately neither the Popen call nor the stdout.read are async. That means the UI will block. This may not be noticeable to you but may have huge impact when you want to use the example in a production setting. I'm still dumbfounded that the create_subprocess_exec from the Python standard library is not working on Windows.

rodja avatar Mar 12 '23 15:03 rodja

I just found https://github.com/tiangolo/fastapi/issues/964 which says that Uvicorn, the ASGI webserver used by FastAPI/NiceGUI is picking the wrong event loop. Can anybody with Windows confirm that without FastAPI/NiceGUI the create_subprocess_exec is working?

rodja avatar Mar 12 '23 15:03 rodja

Thanks, you're right @rodja, it's blocking but I couldn't find better solution.

I used this code to test if create_subprocess_exec works on Windows:

import asyncio

async def test_create_subprocess():
    process = await asyncio.create_subprocess_exec("ipconfig", stdout=asyncio.subprocess.PIPE)
    stdout, stderr = await process.communicate()
    print(stdout.decode())

asyncio.run(test_create_subprocess())

... and it works fine.

spehj avatar Mar 12 '23 19:03 spehj

In the solution to https://github.com/encode/uvicorn/issues/1220 it seems that Uvicorn only changes the event loop if reload is activated. Can someone with Windows verify that the original example works as expected if you set ui.run(reload=False)?

rodja avatar Mar 13 '23 04:03 rodja

@rodja I can confirm that with ui.run(reload=False) the original example works as expected.

spehj avatar Mar 13 '23 07:03 spehj

Great. Then a quick fix for the example would be to use

ui.run(reload=platform.system() != "Windows")

But maybe someone finds another, more sophisticated solution?

rodja avatar Mar 13 '23 08:03 rodja

ui.run(reload=platform.system() != 'Windows') It works, thankyou

LONGER3D avatar Aug 18 '23 02:08 LONGER3D