Remove the "interactive mode"
Discussed in https://github.com/zauberzeug/nicegui/discussions/71
Originally posted by falkoschindler August 26, 2022
When NiceGUI doesn't find a ui.run(), it runs in a so-called "interactive mode". Originally it was introduced to be able to use NiceGUI interactively in Python shells like python or ipython.
Although it is of little use to interactively build UIs, it might be useful to allow importing modules that depend on NiceGUI. E.g. suppose you have written a prime number checker my_prime that comes with a function is_prime(n) and a tiny UI factory method show_sieve_of_eratosthenes(). Thanks to the interactive mode you can start python, import my_prime and fiddle around with the function is_prime(n). NiceGUI is fine with not finding ui.run() and simply doesn't start a server.
The other important use case are PyTests: We might need to import modules that depend on NiceGUI, but there is no ui.run() and thus no server needs to start.
So the purpose of this mode is actually quite clear. But the following questions remain:
- Is it the right name? Interaction is actually not possible, since
ui.run()is forbidden in interactive mode ("Error: Unexpected ui.run() in interactive mode."). - Is the warning correct when importing NiceGUI in a Python shell? "Could not find main script. Starting interactive mode without auto-reload." Actually it is not starting anything.
- Can we detect when running in a PyTest and avoid printing a warning at all?
I tried to remove the interactive mode on this branch: https://github.com/zauberzeug/nicegui/tree/remove_interactive_mode
Looks promising, but needs a bit more testing.
Now I introduced a new flag globals.pre_evaluation_succeeded. This makes decisions in ui.run more explicit, but does not introduce an "internal" configuration flag like interactive was.
I tested the different scenarios with the following test script:
#!/usr/bin/env python3
from nicegui import ui
ui.label('Hello, world!')
print('MAIN', flush=True)
# ui.run(port=1234, title='Test', main_page_classes='', reload=False, dark=True, exclude='three')
# ui.run(port=1234, title='Test', main_page_classes='', reload=True, dark=True, exclude='three')
# ui.run(port=1234+0, title='Test', main_page_classes='', reload=False, dark=True, exclude='three')
# ui.run(port=1234+0, title='Test', main_page_classes='', reload=True, dark=True, exclude='three')
Uncommenting different ui.run lines I checked the following aspects:
- Without
ui.run: "MAIN" is be printed exactly once and no server is started (the script simply terminates). - With
port=1234pre-evaluation succeeds and all arguments are taken into account:- The page runs on port 1234.
- The title is set to "Test".
- There are no margins (caused by clearing
main_page_classes). - The background is dark.
- The three.js library is not served.
- With
port=1234+0pre-evaluation fails. Everything still works, but:- If
reload=True, a warning is shown that main will run a second time. "MAIN" is printed twice. - If
excludeis non-empty, a warning is show that this argument is ignored (excludehas to be known at import phase).
- If
Everything seems to work as expected.
By the way: The previous implementation opens the browser on 127.0.0.1 if NiceGUI is started with host=0.0.0.0 - but only if reload=True. The new implementation uses 127.0.0.1 consistently.
I merged the branch into main. This is the diff: https://github.com/zauberzeug/nicegui/compare/426f420a0fa427979797e1e0c275edf0fc771c0d...30010cd6a12142deff62ada34bf511750cc494ed
I created a new release v0.8.9.