Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the Streamlit submodule to support top-level await #514

Merged
merged 3 commits into from
Mar 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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