Skip to content

Commit

Permalink
Update the Streamlit submodule to support top-level await (#514)
Browse files Browse the repository at this point in the history
* Update the Streamlit submodule to support top-level await

* Rewrite the charts.audio example to load the external resource with async pyodide.http.pyfetch() since stlite now supports top-level await

* Update README.md
  • Loading branch information
whitphx authored Mar 19, 2023
1 parent 6eb79b5 commit 882c60f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 6 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,30 @@ As _stlite_ runs on the web browser environment ([Pyodide](https://pyodide.org/)
- `st.progress()` does not show the progress bar during the script execution, but shows only the last state after the execution finishes.
- `time.sleep()` is no-op. This is a problem at Pyodide runtime. See https://github.com/pyodide/pyodide/issues/2354
- `st.experimental_data_editor` does not work as it relies on PyArrow, but it doesn't work on Pyodide. Track this issue on https://github.com/whitphx/stlite/issues/509.
- For URL access, `urllib` or `requests` don't work on Pyodide/stlite, so we have to use alternative methods provided by Pyodide, such as [`pyodide.http.pyfetch()`](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.pyfetch) or [`pyodide.http.open_url()`](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.open_url). See https://pyodide.org/en/stable/usage/faq.html#how-can-i-load-external-files-in-pyodide for the details. For `pyodide.http.pyfetch()`, see also the following section about top-level await.
- The C extension packages that are not built for Pyodide cannot be installed. See https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel for the details.

Other problems are tracked at GitHub Issues: https://github.com/whitphx/stlite/issues
If you find a new problem, please report it.

## Top-level await

Unlike the original Streamlit, stlite supports top-level await due to the differences in their execution models. Streamlit runs in a standard Python environment, allowing the use of `asyncio.run()` when an async function needs to be executed within a script. In contrast, stlite runs in a web browser, operating in an environment where the only event loop is always in a running state. This makes it impossible to use `asyncio.run()` within a script, necessitating the support for top-level await.

Top-level await can be useful in various situations, such as when accessing external resources. In the Pyodide environment, widely-used URL access methods in Python, like `requests`, are not available. However, Pyodide provides [`pyodide.http.pyfetch()`](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.pyfetch) as an alternative for accessing external resources. Since this method is async, top-level await becomes handy for utilizing `pyodide.http.pyfetch()`.

Here's a sample code snippet demonstrating the usage of top-level await with `pyodide.http.pyfetch()`:

```python
import pyodide.http

url = "your_url_here"
response = await pyodide.http.pyfetch(url)
data_in_bytes = await response.bytes()
```

This code snippet shows how to use top-level await to fetch data from an external resource using `pyodide.http.pyfetch()` and retrieve the response data in bytes format.

## Resources

- [📖 Streamlit meets WebAssembly - stlite, by whitphx](https://www.whitphx.info/posts/20221104-streamlit-wasm-stlite/): A blog post covering from some technical surveys to the usages of the online editor _stlite sharing_, self-hosting apps, and the desktop app bundler.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import requests
import streamlit as st
import pyodide.http


@st.cache_data
def read_file_from_url(url):
async def read_file_from_url(url):
# st.cache_data does not work on async functions,
# so we cache the data manually in st.session_state.
cache_key = f"audio_data_{url}"
if cache_key in st.session_state:
return st.session_state[cache_key]

headers = {
"User-Agent": "StreamlitDocs/1.5.0 (https://docs.streamlit.io; hello@streamlit.io)"
}
return requests.get(url, headers=headers).content
res = await pyodide.http.pyfetch(url, headers=headers)
data = await res.bytes()
st.session_state[cache_key] = data
return data


file_bytes = read_file_from_url(
# stlite supports top-level await.
file_bytes = await read_file_from_url(
"https://upload.wikimedia.org/wikipedia/commons/c/c4/Muriel-Nguyen-Xuan-Chopin-valse-opus64-1.ogg"
)

Expand Down
2 changes: 1 addition & 1 deletion streamlit

0 comments on commit 882c60f

Please sign in to comment.