카테고리 없음

스파르타 AI-8기 TIL(12/1)-Streamlit

kimjunki-8 2024. 12. 1. 21:42
st.session_state
st.session_state는 Streamlit 애플리케이션에서 상태를 저장하고 관리하는 객체입니다. 이 객체는 애플리케이션의 세션 동안 지속되는 데이터를 저장할 수 있게 해줍니다. 사용자가 입력한 값이나 상태 정보 등을 저장하고, 이를 앱 내에서 참조할 수 있습니다. st.session_state는 사용자가 정의한 변수들을 포함하며, 기본적으로 속성이나 값이 비어 있을 수도 있습니다.
예를 들어, 사용자가 로그인한 상태를 추적하고 싶다면, st.session_state.logged_in 같은 속성을 설정할 수 있습니다. 그러나 st.session_state는 기본적으로 속성들을 미리 정의하지 않기 때문에, 사용자가 세션 상태를 설정하고 사용하는 방식에 따라 다양한 속성이 추가될 수 있습니다.

주요 기능
세션 상태 저장: st.session_state는 사용자의 세션 데이터(상태)를 저장할 수 있는 딕셔너리처럼 동작합니다. 세션 상태는 서버와 사용자 간에 유지되며, 사용자가 애플리케이션을 새로 고침해도 상태를 유지할 수 있습니다.
상태 공유: 여러 페이지 간에 세션 상태를 공유할 수 있어서 사용자의 로그인 상태나 입력 데이터를 여러 화면에서 일관되게 유지할 수 있습니다.
상태 유지: 예를 들어, 로그인한 사용자의 정보나 필터링된 데이터 등을 세션 상태에 저장하면, 사용자가 페이지를 새로 고침하거나 다른 페이지로 이동하더라도 해당 정보가 유지됩니다.

1. 세션 상태에 값을 설정하고 저장하기
import streamlit as st

# 세션 상태에 'logged_in'이라는 속성을 추가하고 기본값을 False로 설정
if "logged_in" not in st.session_state:
    st.session_state.logged_in = False

# 로그인 상태 확인
if st.session_state.logged_in:
    st.write("You are logged in!")
else:
    st.write("You are not logged in.")​


2. 값을 업데이트하기

import streamlit as st

# 로그인 상태 변경
st.session_state.logged_in = True
st.session_state.username = "user123"


3. st.session_state의 속성 추가 및 관리
st.session_state는 사용자가 명시적으로 정의할 때만 속성이 생깁니다. 초기에는 빈 딕셔너리처럼 동작합니다. 예를 들어, 사용자가 로그인한 상태나 데이터를 세션에 저장하려면:

import streamlit as st

# 'username' 속성이 없는 경우에만 추가
if "username" not in st.session_state:
    st.session_state.username = ""

# 'username' 출력
st.write(f"Welcome, {st.session_state.username}")

 


일반적으로 사용할 수 있는 속성들:
st.session_state.logged_in: 사용자가 로그인한 상태를 추적하는 변수.
st.session_state.username: 로그인한 사용자의 이름.
st.session_state.cart: 쇼핑몰 애플리케이션에서 사용자가 장바구니에 담은 상품 목록.
st.session_state.user_preferences: 사용자의 설정 정보.
st.session_state.query_results: 검색 결과 또는 계산된 데이터 저장.
기억해야 할 점은, 이건 거의 대부분 디폴트로 이렇게 적을 뿐, 이름을 마음대로 바꿀 수 있습니다. 사용자가 원한느 값으로 변경할 수 있다는 뜻입니다.

st.session_state에 값을 넣어주는 방법은 매우 간단합니다. 딕셔너리처럼 키를 설정하거나 속성으로 접근하여 값을 지정할 수 있습니다. 아래는 두 가지 주요 방식과 예시입니다.

1. 딕셔너리처럼 사용하기
Streamlit의 st.session_state는 딕셔너리와 같은 인터페이스를 제공하므로, 다음과 같이 값을 설정할 수 있습니다:
st.session_state["key_name"] = value

 

예시:
import streamlit as st

# 값 설정
st.session_state["logged_in"] = True
st.session_state["username"] = "user123"

# 값 출력
st.write(f"Logged in: {st.session_state['logged_in']}")
st.write(f"Username: {st.session_state['username']}")​

하지만 주의해야할 사항이 있습니다.
예를 들어

st.session_state["user_name"] = 'kevin'
st.session_state["user_name"] = 'brix'

이렇게 값을 넣을 경우, 기존 값을 덮어씌웁니다. 즉 kevin이라는 값은 brix의 값에 의해 사라집니다. 동일한 키에 여러 값을 추가하거나 저장하지 않습니다. 그렇게 최종적으로 st.session_state["user_name"]에는 "brix"만 남습니다.
즉, 같은 키에 여러 값을 저장하려면 리스트나 다른 자료구조를 사용해야 합니다.

리스트 사용 예시:

if "user_names" not in st.session_state:
    st.session_state["user_names"] = []

st.session_state["user_names"].append("kevin")
st.session_state["user_names"].append("brix")

st.write(st.session_state["user_names"])

결과: ["kevin", "brix"]

또는

import streamlit as st

# 세션 초기화
if "user_info" not in st.session_state:
    st.session_state["user_info"] = {}  # 'user_info'를 딕셔너리로 초기화

# user1, user2의 정보 추가
st.session_state["user_info"]["user1"] = {"name": "Alice", "logged_in": True}
st.session_state["user_info"]["user2"] = {"name": "Bob", "logged_in": False}

# 특정 사용자 정보 접근
user1_info = st.session_state["user_info"]["user1"]
st.write(f"User1's Name: {user1_info['name']}, Logged in: {user1_info['logged_in']}")

# 전체 사용자 정보 출력
st.write("All Users Info:", st.session_state["user_info"])

이렇게 st.session_state["user_info"]["user1"]처럼 작성하면 중첩 구조를 만들어, 세션 상태에 하위 설정이나 추가 정보를 저장할 수 있는 방식입니다.

이 방법은 st.session_state 내부에 딕셔너리를 사용해서, 데이터를 계층적으로 관리할 수 있도록 도와줍니다.


2. 속성처럼 사용하기
st.session_state는 속성 스타일로도 값을 설정할 수 있습니다:
st.session_state.key_name = value

예시:

import streamlit as st

# 값 설정
st.session_state.logged_in = True
st.session_state.username = "user123"

# 값 출력
st.write(f"Logged in: {st.session_state.logged_in}")
st.write(f"Username: {st.session_state.username}")

속성처럼 값을 저장할 때에도 리스트나 다르게 값을 여러개 넣을 수 있다.

import streamlit as st

# 세션 초기화
if "usernames" not in st.session_state:
    st.session_state["usernames"] = []  # 빈 리스트 생성

# 값 추가
st.session_state["usernames"].append("user123")
st.session_state["usernames"].append("user456")

# 값 출력
st.write("Usernames:", st.session_state["usernames"])



값을 업데이트할 때 주의할 점
값을 업데이트하려면 키가 이미 st.session_state에 존재해야 합니다. 만약 존재하지 않으면, Python은 새로운 키나 속성을 추가합니다.
import streamlit as st

# 키가 없는 경우 초기화
if "counter" not in st.session_state:
    st.session_state.counter = 0

# 버튼 클릭 시 값 증가
if st.button("Increment"):
    st.session_state.counter += 1

# 출력
st.write(f"Counter: {st.session_state.counter}")
그런데 이렇게 볼때,
st.session_state["user_names"]랑 st.session_state.logged_in의 차이는 뭐지? 라는 의문이 생길 수 있습니다.
확실히 첫번째 방법이 더 많은 값과 쉽게 값을 바꿀 수 있다는 방법이기 때문에 두번째 방법은 왜 쓰이는지 모르실 수 있습니다.
여기서 알아야 할 점은
상황에 맞게 써야 한다입니다. 저마다 쓸 수 있는 방향과 의미가 다르므로, 상황에 맞게 쓸 수 있어야 합니다.
import streamlit as st

# 초기화
if "logged_in" not in st.session_state:
    st.session_state.logged_in = False

# 사용자 입력
username = st.text_input("Username")
password = st.text_input("Password", type="password")

# 로그인 확인
if st.button("Log In"):
    if username == "admin" and password == "1234":
        st.session_state.logged_in = True
        st.success("Logged in successfully!")
    else:
        st.error("Invalid username or password")

# 로그아웃 버튼
if st.session_state.logged_in and st.button("Log Out"):
    st.session_state.logged_in = False
    st.info("Logged out.")

# 상태 출력
st.write(f"Logged in: {st.session_state.logged_in}")​
이처럼 True, False와 같이 특수한 상황에 맞춰서 쓸 수 있습니다.

하지만 조심해야 할 점은, if "logged_in" not in st.session_state:에서 "logged_in"과 st.session_state.logged_in = True에서 .logged_in은 같은 이름이어야 합니다.

이유는 st.session_state가 파이썬의 딕셔너리처럼 동작하기 때문에, st.session_state["logged_in"]과 st.session_state.logged_in은 사실상 동일한 키를 나타냅니다. 즉, "logged_in"은 키이고, .logged_in은 속성에 접근하는 방법입니다. 두 방식 모두 같은 값을 참조합니다.

일단 이렇게 써보자..여기까지..