Skip to content

Importing nicegui affects mp.set_start_method, throws context has already been set #3644

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

Closed
EricCousineau-TRI opened this issue Aug 29, 2024 · 8 comments

Comments

@EricCousineau-TRI
Copy link

Description

Using nicegui == 1.4.34, CPython 3.10.12, on Ubuntu 22.04.

The following works fine:

$ python -c 'import multiprocessing as mp; mp.set_start_method("spawn")'

The following, however, fails:

$ python -c 'import nicegui; import multiprocessing as mp; mp.set_start_method("spawn")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.10/multiprocessing/context.py", line 247, in set_start_method
    raise RuntimeError('context has already been set')
RuntimeError: context has already been set
@rodja
Copy link
Member

rodja commented Aug 30, 2024

I currently have not the time to dig deeper but it seems to be related to the auto-reloading mechanism of uvicorn. I could reproduce the same behaviour without NiceGUI:

import multiprocessing as mp
import uvicorn

mp.set_start_method("spawn")

if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

If you set ui.run(reload=False) the start method can be set.

@falkoschindler
Copy link
Contributor

We don't think this is an issue with NiceGUI.
If you wish to be able to change the start method in a NiceGUI app (without force=True), feel free to create a feature request or even a pull request. Thanks!

@falkoschindler falkoschindler closed this as not planned Won't fix, can't repro, duplicate, stale Sep 2, 2024
@EricCousineau-TRI
Copy link
Author

Thanks for the feedback!

The underlying issue is importing either nicegui (or something it imports) creates a side effect where we can neither call multiprocessing.set_start_method("spawn").

Note that the error above happens before any code is actually "run" -- I am not calling app.run(...) or uvicorn.run(...).
Perhaps the issue is not with nicegui, but something in the import chain is causing a functional side effect at import time, which ideally should happen when code is explicitly called (e.g. via the main() function).

For us, we simply worked around it by deferring the import of any nicegui components to our main() function. This works, but is a little "dirty".

Does this make sense?

@EricCousineau-TRI
Copy link
Author

Also note that the above still fails for nicegui == 2.0.1.

It does not fail for uvicorn == 0.30.6:

$ python -c 'import multiprocessing as mp; import uvicorn; mp.set_start_method("spawn")'
# No error.

@EricCousineau-TRI
Copy link
Author

If I import nicegui, then collect all the modules registered in sys.modules, and import them individually, it seems like nicegui is the only module that, when imported, causes an issue:
EricCousineau-TRI/repro@3d7cd94

So this seems like it would indicate an issue somewhere in nicegui.

@rodja
Copy link
Member

rodja commented Sep 4, 2024

So this seems like it would indicate an issue somewhere in nicegui.

Sure. I can reproduce it with NiceGUI. But as said, it can be also be reproduced with uvicorn alone. So the underlying problem is "upstream". Maybe there is a workaround we can implement in NiceGUI, but I doubt that.

Note that the error above happens before any code is actually "run"

At first glance it looks that way. But it's important to understand the full startup process: With ui.run(reload=True) (which is the default), the main module is executed twice. Uvicorns main first process spawns a subprocess and launches the actual server which is killed and relaunched on file change" as we wrote in our FAQ.

@davetapley
Copy link

@rodja FYI it's no long reproducible upstream in uvicorn:

$ pip show uvicorn | grep Version
Version: 0.34.0
$ python -c 'import multiprocessing as mp; import uvicorn; mp.set_start_method("spawn")'

$ pip show nicegui | grep Version
Version: 2.14.0
$ python -c 'import multiprocessing as mp; import nicegui; mp.set_start_method("spawn")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/python/3.12.2/lib/python3.12/multiprocessing/context.py", line 247, in set_start_method
    raise RuntimeError('context has already been set')

@davetapley
Copy link

Once #4613 is merged this will work with:

set_start_method("spawn", force=True)
ui.run(title='My App', port=8081, reload=False, require_main_process=False)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants