streamlit: New cache methods cannot hash functions passed as arguments

Summary

I used to have an helper function, which was functioning as a wrapper whenerver I wanted to call a function from a library and cache it in streamlit:

@st.cache_resource
def from_cache(func, *args, **kwargs):
    return func(*args, **kwargs)

which was called as:

from some library import some_library_function

from_cache(some_library_function, an_arg, some_other_arg=arg_value)

Since st.cache is now deprecated, I tried the new caching methods st.cache_data and st.cache_resource, but it seems that none of them is able to cache functions, raising a:

streamlit.runtime.caching.cache_errors.UnhashableParamError: Cannot hash argument 'func' (of type `builtins.function`) in 'from_cache'.

Is there any way to get the desired behaviour in the new version?

Is this a regression?

  • Yes, this used to work in a previous version.

Debug info

  • Streamlit version: 1.19.0
  • Python version: 3.9

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (1 by maintainers)

Most upvoted comments

We could consider doing something like hashing the callable’s bytecode, but I don’t love the idea for a few reasons:

  • that will miss any external state that the function relies on to do its job. (Say you have a closure that reads a closed-over variable, or a function that reads a global or something - hashing the function’s bytecode wouldn’t catch the fact that the function may return different outputs for the same input.)
  • Not all Callables have hashable bytecode, I think? A function has a __code__ property we can hash, but not all Callables are functions. (This isn’t necessarily fatal: we could consider just supporting proper functions, and error when trying to hash non-function callables - but that may not entirely solve your use case, @andreaschiappacasse?)

Our old caching code did try to hash everything under the sun, but it many ugly edge cases and weird failure states that could introduce subtle, surprising bugs if used incorrectly. The new caching code attempts to have fewer footguns; sometimes this means it omits unsafe functionality we had before.