Skip to content
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

[BUG] Background callbacks with different outputs not working #2221

Closed
daviddavo opened this issue Sep 8, 2022 · 5 comments · Fixed by #2473
Closed

[BUG] Background callbacks with different outputs not working #2221

daviddavo opened this issue Sep 8, 2022 · 5 comments · Fixed by #2473

Comments

@daviddavo
Copy link

Describe your context
Please provide us your environment, so we can easily reproduce the issue.

  • replace the result of pip list | grep dash below
dash                      2.6.1
dash-bootstrap-components 1.2.0
dash-core-components      2.0.0
dash-html-components      2.0.0
dash-table                5.0.0

Describe the bug

Background callbacks don't work if they are generated with a function/loop. For example, I've created a function gen_callback that creates a new callback given a css id.

def gen_callback(css_id, x):
        @app.callback(
            Output(css_id, 'children'),
            Input('my-dropdown', 'value'),
            background=True,
        )
        def callback_name(value):
            print(f"Inside callback_name {self._css_id} for {org_id}")

            return int(value) + x

The background callback manager uses a hash function to know the key to get. This hash function just takes into account the code of the function, but not the variables used to generate that function.

@staticmethod
def hash_function(fn):
fn_source = inspect.getsource(fn)
fn_str = fn_source
return hashlib.sha1(fn_str.encode("utf-8")).hexdigest()

I think the hash should also take into account the Output list of the callback.

Expected behavior

Using a variable as the id of one of the outputs creates multiple different, valid callbacks, that should work fine with background=True.

Possible temporary solution

Generate a function with exec(), replacing parts of a template code, and decorate the compiled function.

@LuisScoccola
Copy link

I have a very similar problem. In case this is useful, I have been using the following workaround for now. I do not know if the workaround breaks any other Dash functionality.

In the file that defines the Dash app, I added:

from dash.long_callback.managers import BaseLongCallbackManager
import uuid

def monkeypatched_hash_function(fn):
    return uuid.uuid4()

BaseLongCallbackManager.hash_function = monkeypatched_hash_function

@daviddavo
Copy link
Author

But then it won't be cached, because every time the hash function is called it will return a different uuid.

@LuisScoccola
Copy link

If I am not mistaken, the only time the hash function is called is when registering a function, and this is done only once per function (i.e., only once each time Dash's callback function is invoked). By looking at the code, it seems that the hash is only used as a key to then find the function that must be run when a certain callback is triggered. Thus, it seems that the only purpose of the hash is to assign a unique key each time a function is registered. Since I am not a Dash developer, I can of course be wrong, and please do let me know if I have misunderstood your issue. In any event, the workaround I proposed does work for me.

@daviddavo
Copy link
Author

Sorry, I meant that it wouldn't be cached between runs. If you restart the program, the uuids will be different.

@hydrusbeta
Copy link

Thank you for fixing this issue! I recently ran into this exact problem, and it went away after I updated dash to the latest version.

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

Successfully merging a pull request may close this issue.

3 participants