Pretty way to change a function’s parameters via st.dropdown if these parameters are not in app.py?

Hi guys,

Not sure if there’d be a pretty way to change a function’s parameters via st.dropdown if these parameters are actually located in a secondary Python file? Please see screenshot below for context:

At the moment, I’ve having to paste all these secondary files in app.py… and that monlithic bloc is neither handy nor pretty! :grinning_face_with_smiling_eyes:

Thanks,
Charly

How about using session state to hold kwargs selected in the dropdown? Can’t you pass them directly as parameters?

Alternatively, put the components that are serving the app behind a FastAPI microservice running on a separate thread.

HOST = 'localhost'
PORT = 8000

def thread_runner(app, host, port):
    uvicorn.run(app, host=host, port=port)

app = FastAPI()
@app.get('/prepare_query')
def prepare_query(**kwargs):
    for name, val in kwargs.items():
        # build your query string here, do the work, and return response
        pass

thread = threading.Thread(name='QueryServer', target=thread_runner, args=(app, HOST, PORT))
thread.start()
1 Like

Hey @Charly_Wargnier,

So what you want to do is change the behavior of that suggests library, and more specifically add a custom parameter to change the language part of the following hardcoded string:

The cleanest solution would be to fork and patch the library to add a new parameter, create your PyPI and build your streamlit app on top of it.

Another solution would be to patch the library’s function directly from your app.

import streamlit as st
import suggests

from streamlit.report_thread import get_report_ctx
from streamlit.server.server import Server
from types import SimpleNamespace


def get_session():
    session_id = get_report_ctx().session_id
    session_info = Server.get_current()._get_session_info(session_id)

    if session_info is None:
        raise RuntimeError("Couldn't get your Streamlit Session object.")
    
    return session_info.session


def get_state():
    session = get_session()

    if not hasattr(session, "_custom_session_state"):
        session._custom_session_state = SimpleNamespace()

    return session._custom_session_state


def custom_get_google_url():
    # Retrieves language from session state
    lang = get_state().lang

    return f"https://www.google.com/complete/search?sclient=psy-ab&hl={lang}&q="


# Stores language in session state
state = get_state()
state.lang = st.selectbox("Language", ["en", "fr", "es"])


# Here we replace suggests's function by our own
suggests.get_google_url = custom_get_google_url

Two things to note here:

  • You must do an import suggests instead of from suggests import get_google_url to patch the function, like done above. suggests.get_google_url = ... redefines the function used by the library, whereas get_google_url = ... is just a regular assignment.

  • Patching a library’s function is done globally, so to make sure each user session uses its own language parameter, I retrieve the latter through a very basic session state implementation which will keep track of the language selected by each user. Without session state, you might run into race condition issues where one user might use the language parameter of another user connected to your app.

2 Likes