-
-
Notifications
You must be signed in to change notification settings - Fork 599
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Callbacks vs Streamlit-Like "if"-statements #1
Comments
Hi Eli, Our problem with Streamlit was mainly due to the way it handles user interaction. Writing State If the script starts with loading some non-constant initial state, e.g. from an external source, this state is reset whenever the script is processed again. The following script already shows inconsistent behavior. Initializing
It is hard to let Streamlit load the state once and let the user update it repeatedly. It gets worse when multiple widgets interact with each other, like a button resetting the radio selection to some value. There are workarounds introducing session state. But they are not trivial and require quite some additional code. You can look into one of our projects to see how we mapped machine state onto session state to make it accessible for Streamlit: Loops Always reloading the script makes it also difficult to introduce own event loops, e.g. reading data and updating a plot repeatedly. In the above-mentioned project we found a workaround using threads that need to get stopped and restarted every time the script restarts due to user interaction: Today (on the main branch) we avoid this struggle using NiceGUI: Handling user interaction without callbacks seems indeed intriguing. But we doubt it holds for slightly more demanding projects. It’s just not like the language works: A (non-blocking) if-statement evaluates the conditional expression to decide which path to take, before the user gets the chance to interact. Doing it otherwise requires Streamlit to perform a significant amount of "magic", causing trouble in other respects. |
Thank you very much for the detailed answer Falko. It does indeed look that Streamlit has a serious design flaw. They tried making things very simple, but that ended limiting the utility of their framework. |
I renamed the issue from Improvements in JustPy to Callbacks vs Streamlit-Like "if"-statements for better clarification of the topic. |
@elimintz I was curious to see whether I could come up with Streamlit-like if-statements for NiceGUI (or JustPy) UI elements that postpone code execution until an event occurs, but don't require re-running the whole script. Although I don't think it's super reliable and it could break in more complicated scenarios, it's interesting to see what is possible. #!/usr/bin/env python3
from nicegui import ui
import inspect
import ast
def magic_button(text):
class NodeVisitor(ast.NodeVisitor):
def __init__(self, lineno):
self.lineno = lineno
self.node = None
def visit_If(self, node):
if node.lineno == self.lineno:
self.node = node
self.generic_visit(node)
frame = inspect.currentframe().f_back
with open(inspect.getsourcefile(frame)) as f:
code = f.read()
tree = ast.parse(code)
visitor = NodeVisitor(inspect.currentframe().f_back.f_lineno)
visitor.visit(tree)
block = code.splitlines()[visitor.node.lineno:visitor.node.end_lineno]
indentation = min(len(line) - len(line.lstrip()) for line in block)
block = '\n'.join(line[indentation:] for line in block)
ui.button(text, on_click=lambda _: exec(block, frame.f_globals, frame.f_locals))
ui.label('This script demonstrates postponed code execution with streamlit-like if-statements.')
count_label = ui.label('count = 0')
count = 0
if magic_button('Click me!'):
count += 1
print(f'count = {count}')
count_label.text = f'count = {count}' When creating a "magic button", the source code is parsed into a tree and traversed looking for if-statements on the same line from which The question remains, how "nice" and pythonic it is to bend the normal flow of code execution. As Streamlit shows, it's easy to find examples where such an approach leads to unexpected behavior. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Hi,
I like very much what you did with nicegui and how you used justpy! Very nice.
I also looked at streamlit. Could you expound a little about why that was not a good solution for you in the end?
One feature of streamlit that I find intriguing is the ability to assign the value of a component to a variable without the need of callbacks. Of course, the callbacks happen but are transparent to the user of the framework. I am trying to think how this could be implemented in JustPy. It would be a great feature for nicegui, making it even simpler to use. What is your view on this and how do you think it could be implemented?
If you prefer to have the discussion by email instead of here, my email is [email protected] or you can also open an issue in the JustPy repository.
Eli
The text was updated successfully, but these errors were encountered: