-
Notifications
You must be signed in to change notification settings - Fork 649
Open
Description
Checklist
- I have searched the existing issues for similar issues.
- I added a very descriptive title to this issue.
- I have provided sufficient information below to help reproduce this issue.
Summary
Instead of using Python’s hashing semantics, Streamlit attempts to serialize (pickle) function arguments to bytes and hashes those bytes, which leads to surprising and misleading UnhashableParamErrors.
This behavior conflicts with the doc A function's arguments must be hashable to cache it.
This behavior is conceptually incorrect and violates the expectation that “hashable objects are cacheable”, where st.cache_resource is explicitly process-local and does not provide cross-process persistence, and where Python’s own functools.lru_cache accepts any object that is hashable according to standard Python semantics, without imposing serialization requirements.
Reproducible Code Example
import streamlit as st
class Data:
def __init__(self, payload: bytes):
self.payload = payload
@st.cache_resource
def transform(data: Data) -> Data:
return Data(payload=b'new')
data = Data(payload=b'old')
st.write(st.__version__)
st.write(data)
st.write(hash(data))
st.write(transform(data)) # <-- throw errorSteps To Reproduce
No response
Expected Behavior
No response
Current Behavior
Output:
1.50.0
dataData__main__.Data(payload: bytes)
No docs available
payloadbytes | b'old'
-- | --
8779468763100
Error message:
# _to_bytes <class '__main__.Data'>: <__main__.Data object at 0x7fc211defdc0>
# _to_bytes <class 'function'>: <function _reconstructor at 0x7fc2af172560>
────────────────────────── Traceback (most recent call last) ───────────────────────────
ntime/caching/hashing.py:648 in _to_bytes
_reduce_ex
73 │ │ state = None
74 │ else:
75 │ │ if base is cls:
❱ 76 │ │ │ raise TypeError(f"cannot pickle {cls.__name__!r} object")
77 │ │ state = base(self)
78 │ args = (cls, base, state)
79 │ try:
────────────────────────────────────────────────────────────────────────────────────────
TypeError: cannot pickle 'function' object
The above exception was the direct cause of the following exception:
────────────────────────── Traceback (most recent call last) ───────────────────────────
ntime/caching/hashing.py:650 in _to_bytes
────────────────────────────────────────────────────────────────────────────────────────
UnhashableTypeError
During handling of the above exception, another exception occurred:
────────────────────────── Traceback (most recent call last) ───────────────────────────
ntime/caching/hashing.py:650 in _to_bytes
────────────────────────────────────────────────────────────────────────────────────────
UnhashableParamError: Cannot hash argument 'data' (of type `__main__.Data`) in
'transform'.
Is this a regression?
- Yes, this used to work in a previous version.
Debug info
- Streamlit version: 1.50.0
- Python version: Python 3.10.19
- Operating System:
- Browser:
Additional Information
No response
github-actions
Metadata
Metadata
Assignees
Labels
No labels