Caching and class inheritance

EDIT: I came back to this a few days later and without changing anything it worked when I ran it.

Summary

I have created an ImageGallery class that creates a gallery of images using columns, this works on its own with @st.cache_resource applied to the class (not method). I want to create a child class for a MapGallery so I can override the fetch_files() method, this doesn’t work with either of the caching decorators but works without them.

Steps to reproduce

Code snippet:

import streamlit as st

@st.cache_resource(show_spinner="Refreshing gallery...")
class ImageGallery():
    def __init__(self, directory, expanded=True, file_extensions=(".png", ".jpg", ".jpeg"), label="**Images**"):
        self.directory = directory
        self.expanded = expanded
        self.file_extensions = file_extensions
        self.label = label
        self.gallery = self.create_gallery()

    def fetch_files(self):
        self.all_files = list()
        self.all_filenames = list()
        for item in self.directory.rglob("*"):
            if item.is_file() and item.name.endswith(self.file_extensions):
                self.all_files.append(str(item.resolve()))
                self.all_filenames.append(str(item.name))
        return self.all_files, self.all_filenames

    def create_gallery(self):
        self.source_image_dropdown = st.expander(label=self.label, expanded=self.expanded)
        with self.source_image_dropdown:
            self.source_gallery = st.container()
        with self.source_gallery:
            self.col1, self.col2, self.col3, self.col4, self.col5 = st.columns(5)
            self.col_list = [self.col1, self.col2, self.col3, self.col4, self.col5]
            self.col_idx = 0
            self.filename_idx = 0
            self.gallery_files, self.gallery_filenames = self.fetch_files()
            for img in self.gallery_files:
                with self.col_list[self.col_idx]:
                    st.image(img, caption=self.gallery_filenames[self.filename_idx], use_column_width=True)
                    if self.col_idx < 4:
                        self.col_idx += 1
                    else:
                        self.col_idx = 0
                    self.filename_idx += 1
        return self.source_image_dropdown

@st.cache_resource(show_spinner="Refreshing gallery...")
class MapGallery(ImageGallery):
    def __init__(self, directory, expanded=True, file_extensions=(".png"), label="**Maps**"):
        super(MapGallery, self).__init__(directory, expanded, file_extensions, label)

    def fetch_files(self):
        self.all_files = list()
        self.all_filenames = list()
        for item in self.directory.rglob("screenshot.*"):
            if item.is_file():
                self.all_files.append(str(item.resolve()))
                self.all_filenames.append(str(item.parent.name))
        return self.all_files, self.all_filenames

    def create_gallery(self):
        return super().create_gallery()

The code above works when the decorator is removed from both classes, I have tried placing the decorator on the method(s) and class(es) but encounter errors which I will try and outline below.

Expected behavior:

The gallery to be created and cached so it doesn’t have to load all the images every time the app reloads. This is what happens if no child class is used and the @st.cache_resource decorator is used on the class.

Actual behavior:

I encounter a few different errors depending on which decorator I use and where I place it, I have listed the errors below and tried to note which decorator is used and where it is placed for each error.

Either decorator used on either of the classes:

TypeError: function() argument 'code' must be code, not str
Traceback:
File "/data/data/com.termux/files/home/git/interactive-map-creator/.venv/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 565, in _run_script
    exec(code, module.__dict__)
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/main.py", line 5, in <module>
    from apps import create, docs, home, maps, uploads
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/apps/maps.py", line 4, in <module>
    from gallery import ImageGallery, MapGallery
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/gallery.py", line 51, in <module>
    class MapGallery(ImageGallery):

@st.cache_resource() used on the create_gallery() method in ImageGallery() class:

For this I had to change self to _self for the create_gallery() method and then get the following error. No error message is produced but it only caches the first gallery it creates and returns that for each call to create a gallery afterwards.

@st.cache_data() used on the create_gallery() method in ImageGallery() class:

For this I had to change self to _self for the create_gallery() method and then get the following error.

StreamlitAPIException: __setstate__() is not a valid Streamlit command.

Traceback:
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/main.py", line 70, in <module>
    app["func"]()
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/apps/uploads.py", line 17, in app
    images_gallery = ImageGallery(directory=utils.images_folder)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/data/com.termux/files/home/git/interactive-map-creator/interactive_map_creator/gallery.py", line 27, in __init__
    self.gallery = self.create_gallery()
                   ^^^^^^^^^^^^^^^^^^^^^

Debug info

  • Streamlit version: Streamlit, version 1.19.0
  • Python version: Python 3.11.2
  • Installed using: Pip 22.3.1
  • OS version: Termux on Android 13, also tested on Fedora 37 x64
  • Browser version: Chrome/Firefox/Kiwi Browser

Requirements file

altair==4.2.2
attrs==22.2.0
blinker==1.5
branca==0.6.0
cachetools==5.3.0
certifi==2022.12.7
charset-normalizer==3.0.1
click==8.1.3
decorator==5.1.1
entrypoints==0.4
folium==0.14.0
GDAL==3.6.2
gitdb==4.0.10
GitPython==3.1.31
idna==3.4
importlib-metadata==6.0.0
Jinja2==3.1.2
jsonschema==4.17.3
markdown-it-py==2.1.0
MarkupSafe==2.1.2
mdurl==0.1.2
numpy==1.24.2
packaging==23.0
pandas==1.5.3
Pillow==9.4.0
protobuf==3.20.3
pyarrow==11.0.0
pydeck==0.8.0
Pygments==2.14.0
Pympler==1.0.1
pyrsistent==0.19.3
python-dateutil==2.8.2
pytz==2022.7.1
pytz-deprecation-shim==0.1.0.post0
requests==2.28.2
rich==13.3.1
semver==2.13.0
six==1.16.0
smmap==5.0.0
streamlit==1.19.0
streamlit-folium==0.11.1
streamlit-option-menu==0.3.2
toml==0.10.2
toolz==0.12.0
tornado==6.2
typing_extensions==4.5.0
tzdata==2022.7
tzlocal==4.2
urllib3==1.26.14
validators==0.20.0
watchdog==2.2.1
zipp==3.14.0

Links

Additional info

Any help is greatly appreciated, thanks for reading this far.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.