-
-
Save Hu-Wentao/4a490de02c520ff009ebff53e1929ec7 to your computer and use it in GitHub Desktop.
streamlit: FilePicker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| UPDATE: Please see https://github.com/Hu-Wentao/st_tools?tab=readme-ov-file#pathfilefolderselector-st_path_selector | |
| """ | |
| import os | |
| from typing import Callable, Any | |
| import streamlit as st | |
| def st_path_selector( | |
| label='选择文件/文件夹', key='st_path_selector', path: str = '.', help: str = None, | |
| ) -> str: | |
| # == | |
| def s_path(update: str = None, navi_to: str = None) -> str: # 核心状态, 选中的path, 可能是文件/文件夹 | |
| if update: # 当path以`/`结尾, 修复路径,移除`/` | |
| update = os.path.normpath(update) | |
| if navi_to is not None: | |
| update = os.path.abspath(os.path.join(s_path_dir(), navi_to)) | |
| return tool_s_state(update, key, init=os.path.abspath(path)) | |
| def s_path_dir(): # 选中路径所在的文件夹(如果选中文件夹则返回文件夹) | |
| _p = s_path() | |
| return _p if os.path.isdir(_p) else os.path.dirname(_p) | |
| def s_path_navi(update: str = None) -> str: # 路径导航, 当前路径到 .. 或到 /foo 等... | |
| return tool_s_state(update, f"{key}.s_path_navi", init=os.path.abspath(path)) | |
| # == | |
| s_path() | |
| c1, c2 = st.columns([3, 1]) | |
| c1.text_input('当前路径', key=key, placeholder='在此处粘贴或在右侧选择 文件/文件夹', | |
| help=help, on_change=st.rerun) | |
| from natsort import natsorted | |
| c2.selectbox( | |
| key=f"{key}.s_path_navi", | |
| label=label, | |
| options=['.', '..', *natsorted(os.listdir(s_path_dir()))], | |
| format_func=lambda | |
| x: f"{'🗂️' if os.path.isdir(os.path.join(s_path_dir(), x)) else '🗒️'} { | |
| ".\t(当前路径)" if x == '.' else | |
| "..\t(上级路径)" if x == '..' else | |
| x}", | |
| on_change=lambda: s_path(navi_to=s_path_navi()) | |
| ) | |
| return s_path() | |
| def tool_s_state(update, k: str, init: Callable[[], Any] | Any = None, | |
| force_update=False, force_init=False): | |
| """ | |
| # see: https://gist.github.com/Hu-Wentao/1711debf08581d6ce25fa78619926b02 | |
| :param force_init: force init value, ignore key in st.session_state | |
| :param force_update: force update value, ignore `update` is or not None | |
| :param update: update state value | |
| :param k: st.state_session state key | |
| :param init: init state value or init function | |
| :return: state | |
| """ | |
| if update is not None or force_update: # 有新值(或强制刷新) | |
| st.session_state[k] = update | |
| elif k not in st.session_state or force_init: # 无值,且未注册key (或强制更新为init) | |
| if isinstance(init, Callable): | |
| _value = init() | |
| else: | |
| _value = init | |
| st.session_state[k] = _value | |
| return st.session_state[k] | |
| if __name__ == '__main__': | |
| selected_path = st_path_selector( | |
| path=".", | |
| label="Choose a file", | |
| key="my_file_selector" | |
| ) | |
| st.info(f"{selected_path=}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment