-
Notifications
You must be signed in to change notification settings - Fork 69
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
reactive.poll doesn't poll when defined in Express-adjacent modules #1079
Comments
It's possible to add an import hook that detects the name of the imported module and does something before and/or after loading that module. For example, here's an import hook in Shinylive for loading seaborn: So we could add an import hook that sets the current session to (Note: we can't use the name Another possibility: when |
Would the import hook be better than preloading it? If it's going to be based on special module names anyway, I think it makes intuitive sense that Shiny would load those modules before loading the first session. |
I just realized another way to do it is to create a new function for importing shared stuff, similar to from shiny.express import import_shared
shared = import_shared("shared.py") |
Would that just call |
Right, it would be something like that. |
I also think we need a dedicated article talking about global vs. session objects and logic (including but not limited to reactives). Right now I believe the only mention of this is at the end of "Express in depth". Maybe this would go along with ways of working with data (loading from database, loading from CSV, global vs. session). cc @cpsievert |
After playing with this for a bit, this is very simple to get to work: def import_shared(module_name: str) -> ModuleType:
with session_context(None):
module = importlib.import_module(module_name)
return module
# Import a shared.py file
shared = import_shared("shared") However, there are a few drawbacks:
Another possible approach is to provide a new context manager for people to use whenever they want to run any code that's meant to be shared across sessions. I'll call it # Definition of function (in shiny.express)
@contextmanager
def app_globals():
with session_context(None):
yield
# Usage in app
with app_globals():
from shared import x All it does is wrap Compared to the
|
Possible path forward:
|
While trying to port this app: https://github.com/posit-dev/py-shiny/blob/9ad2ab12ae0054ac745efed78da5fceb1e09fc43/shiny/api-examples/poll/app.py
I tried defining a
@reactive.poll
in a separate file (data.py), and then using it from the Express app.Full source code
app.py
data.py
This loaded, but did not update. The polling function passed to
@reactive.poll
,tbl_last_modified
, did not execute every 0.5 seconds as expected.The reason for this is because the
data.py
module is only loaded once (exactly the reason why we created it), but at the time that it's loaded, there's a session active--it happens to be a MockSession. When that MockSession closes, any reactive effects that belong to it shut down--in this case, our@reactive.poll
.This is a tough nut because this automatic closing of effects is necessary for ones that really do belong to the session, but
data.py
is intended to be global.I worked around this by passing an explicit
session=None
argument toreactive.poll()
.A fix could be... I don't know, to have a special name for such modules?
global.py
? And we load them first, outside of any session?The text was updated successfully, but these errors were encountered: