Following documentation for matplotlib throws AttributeError: 'RendererAgg' has no attribute 'lock'

My goal is to deploy a web app (originally in Jupyter Notebooks) that generates many complex matplotlib figures. It would take very long to reformat them all into Plotly. From reading the docs and blog posts, it seems like matplotlib will struggle with concurrent users. Currently I’m running it locally, but want to future-proof. The streamlit docs recommend implementing matplotlib with the RendererAgg backend as follows:

# Imports
import streamlit as st
import matplotlib as mp
import matplotlib.pyplot as plt

# # Change matplotlib backend
from matplotlib.backends.backend_agg import RendererAgg
_lock = RendererAgg.lock

# # Generate figure
with _lock:
    fig, axs = plt.subplots(figsize = (5, 5))
    plt.plot([1,2], [0, 0])

# # Render in streamlit
st.pyplot(fig)

This gives me the following error: AttributeError: type object ‘RendererAgg’ has no attribute ‘lock’

AttributeError: type object 'RendererAgg' has no attribute 'lock'
Traceback:
File "C:\...\streamlitenv\Lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py", line 542, in _run_script
    exec(code, module.__dict__)File "D:\...\scrap.py", line 17, in <module>
    _lock = RendererAgg.lock
            ^^^^^^^^^^^^^^^^

If I remove the lines calling _lock (_lock = RendererAgg.lock and with _lock:), my local file displays the plot normally. What is going on with RendererAgg? In my streamlitenv environment, I am running matplotlib 3.8.0, streamlit 1.32.0, and python 3.11.7.

EDIT: fixed formatting

That lock was removed and probably never intended for use by clients, but you can use your own.

1 Like

Thank you so much. Sounds like it’s time to update the doc then.
Am I correctly understanding that you are just saying to run

with RLock:
    fig, ax = plt.subplots()

st.pyplot(fig)

I’ve never done that, but I guess you should use an instance of RLock instead of the class itself.

Also my reading of the comments in the pull request and the bug it closes suggest that you should use always the same instance of RLock, you can use st.cache_resource for that.

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