Programming/Python

Streamlit SessionState

라우드니스 2021. 4. 5. 21:44

이전에 업무에 도움이 되는 간단한 도구를 만들기 위해 R의 Shiny프로젝트를 이용한 적이 있었는데, 분석가분의 R 코드를 재활용하면서 클라이언트 쪽 코드를 개발 안해도 되니 어느 정도 도구의 윤곽이 잡히기 전까지는 유용하게 사용했었던 좋은 기억이 있다. 

 

그래서 이번에는 Streamlit이라는 python용 open source visualization 도구를 사용해 간단한 도구를 만드려고 해보고 있는데 생각보다 UI에 대한 조절 기능이 몇개 없는 것도 불편하지만 특히 reactive 하게 반응하는 UI 컴포넌트들을 다루는게 생각하고 다르게 되어 있어서 배보다 배꼽이 더 큰 상황에 도달했다. 

 

예를 들어, 특정 조건의 데이터를 동적으로 가지고 와 selectbox를 만들고 이 selectbox의 선택을 가지고 다시 동적으로 UI를 만드려고 하는 상황이라면 첫번째 selectbox를 선택하자 마자 모든 python 코드가 다시 실행되서 두번째 selectbox는 선택할수도 없는 문제가 있다. 비슷하게, button 안에 button 안에 button 안에... 이런식으로 button의 성공 여부에 따른 UI를 중첩으로 만들면 하위 UI는 계속해서 새롭게 rendering 되는 페이지 때문에 접근조차 할 수 없다. 

 

그래서 시작부터 얘는 정말 시각화 도구로만 써야하고 간단하게 컨트롤 하는 도구로도 못써먹겠구나, 그냥 웹페이지 하나 만들어야 겠다... 빠르게 포기한 상태로 업무 일정은 재조정했는데 '그래도 혹시?' 하는 생각에 검색을 해보니 streamlit이 내부 session 정보를 저장하는 객체에다가 데이터를 저장하여서 위와 같은 상황이 됐을 때 session 값을 사용해서 python 코드가 다시 실행되는걸 방지하는 객체를 사용자들이 만들어서 공유하고 있는 것을 찾을 수 있었다. 

 

 

python에 익숙하지 않은 분들을 위해 설명하면, 위 코드를 streamlit 코드가 있는 곳에 같이 두면 streamlit 코드에서 import 가능하다.

 

streamlit_code/

|- app.py

|- SessionState.py

 

이런 식으로 app.py가 streamlit을 import 하여 사용하는 python 코드이면 같은 곳에 SessionState.py 라고 위 gist 내의 코드 부분을 저장하면 app.py 에서

 

import streamlit as st
import SessionState

session_state = SessionState.get(button_1=False)

...

button_1 = st.button("Button 1")

if button_1:
  session_state.button_1 = button1

...

 

대충 이런식으로 사용하면 된다. (다른 예제)

반응형