debugging-streamlit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Debugging Streamlit Apps

调试Streamlit应用

Quick Start

快速开始

bash
make debug my_app.py
This starts both backend (Streamlit/Python) and frontend (Vite/React) with hot-reload. The app URL is printed on startup (default
http://localhost:3001
;
3000
is reserved for manual
make frontend-dev
; it may use
3002+
if other debug sessions are running). Avoid pinning
VITE_PORT
unless you have a specific hard requirement (last resort).
Hot-reload behavior:
  • Frontend: Changes to
    frontend/
    code are applied within seconds.
  • Backend: Only changes to the app script trigger a rerun. Changes to the Streamlit library itself (
    lib/streamlit/
    ) require restarting
    make debug
    .
bash
make debug my_app.py
这会启动带热重载功能的后端(Streamlit/Python)和前端(Vite/React)服务。启动时会打印应用URL(默认是
http://localhost:3001
3000
端口预留给手动执行
make frontend-dev
;如果有其他调试会话在运行,可能会使用
3002+
端口)。除非有特定的硬性需求,否则不要固定
VITE_PORT
(这是最后的手段)。
热重载行为:
  • 前端:对
    frontend/
    目录下代码的变更会在数秒内生效。
  • 后端:只有对应用脚本的变更会触发重新运行。对Streamlit库本身(
    lib/streamlit/
    )的修改需要重启
    make debug

Log Files

日志文件

Each
make debug
run writes logs to a per-session directory under
work-tmp/debug/
and updates
work-tmp/debug/latest/
to point at the most recent session. Because
latest/*
is a symlink, it can move if multiple debug sessions are starting/stopping concurrently—prefer using the session directory path printed by
make debug
when you need stable log references. You can find the exact session directory in the
make debug
startup output under the
Log files
section.
FileContent
work-tmp/debug/latest/backend.log
Python
print()
statements, Streamlit logs, errors
work-tmp/debug/latest/frontend.log
Browser
console.log()
, React errors, Vite output
Logs are cleared at the start of each session and persist after exit for post-mortem analysis.
Log size warning: Logs can grow large during extended debugging sessions. Instead of reading entire log files, use
rg
to search for specific patterns:
bash
undefined
每次
make debug
运行都会将日志写入
work-tmp/debug/
下的会话专属目录,并更新
work-tmp/debug/latest/
指向最近的会话。 由于
latest/*
是一个符号链接,当多个调试会话同时启动/停止时,它可能会移动——当你需要稳定的日志引用时,优先使用
make debug
启动输出中打印的会话目录路径。 你可以在
make debug
启动输出的
Log files
部分找到确切的会话目录。
文件内容
work-tmp/debug/latest/backend.log
Python
print()
语句、Streamlit日志、错误信息
work-tmp/debug/latest/frontend.log
浏览器
console.log()
、React错误、Vite输出
日志会在每次会话开始时清空,并在退出后保留以便事后分析。
日志大小警告: 在长时间的调试会话中,日志可能会变得很大。不要直接读取整个日志文件,而是使用
rg
搜索特定模式:
bash
undefined

Search for specific debug messages

搜索特定调试信息

rg "DEBUG:" work-tmp/debug/latest/backend.log
rg "DEBUG:" work-tmp/debug/latest/backend.log

Search for errors (case-insensitive)

搜索错误信息(不区分大小写)

rg -i "error|exception|traceback" work-tmp/debug/latest/backend.log
rg -i "error|exception|traceback" work-tmp/debug/latest/backend.log

Search with context (3 lines before/after)

带上下文搜索(前后3行)

rg -C 3 "my_function" work-tmp/debug/latest/backend.log
rg -C 3 "my_function" work-tmp/debug/latest/backend.log

Search frontend logs for specific component

搜索前端日志中的特定组件

rg "MyComponent" work-tmp/debug/latest/frontend.log

Use this directory for all debugging artifacts (scripts, screenshots, etc.) to keep them organized.
rg "MyComponent" work-tmp/debug/latest/frontend.log

将所有调试产物(脚本、截图等)放在这个目录中,以便保持整洁。

Adding Debug Output

添加调试输出

Backend (Python):
python
print(f"DEBUG: session_state = {st.session_state}")
Frontend (TypeScript/React):
typescript
console.log("DEBUG: props =", props)
Frontend
console.log()
output appears in
work-tmp/debug/latest/frontend.log
(or the current session's
frontend.log
file).
后端(Python):
python
print(f"DEBUG: session_state = {st.session_state}")
前端(TypeScript/React):
typescript
console.log("DEBUG: props =", props)
前端的
console.log()
输出会出现在
work-tmp/debug/latest/frontend.log
(或当前会话的
frontend.log
文件)中。

Workflow

工作流

  1. Create or use a test script in
    work-tmp/debug/
    (e.g.,
    work-tmp/debug/test_feature.py
    )
  2. Run
    make debug work-tmp/debug/test_feature.py
  3. Verify startup: Check
    work-tmp/debug/latest/backend.log
    for
    Error
    /
    Exception
    and
    work-tmp/debug/latest/frontend.log
    for console errors to ensure both servers started correctly
  4. Access the printed App URL in your browser (default
    http://localhost:3001
    , but it may be
    3002+
    )
  5. Verify script execution: Check
    work-tmp/debug/latest/backend.log
    again for any errors after the first app access
  6. Monitor logs by inspecting
    work-tmp/debug/latest/backend.log
    and
    work-tmp/debug/latest/frontend.log
  7. Edit code - changes apply automatically via hot-reload
  8. Check logs for debug output
Quick error check:
bash
undefined
  1. work-tmp/debug/
    中创建或使用测试脚本(例如
    work-tmp/debug/test_feature.py
  2. 运行
    make debug work-tmp/debug/test_feature.py
  3. 验证启动状态:检查
    work-tmp/debug/latest/backend.log
    中的
    Error
    /
    Exception
    ,以及
    work-tmp/debug/latest/frontend.log
    中的控制台错误,确保两个服务都正常启动
  4. 在浏览器中访问打印的应用URL(默认是
    http://localhost:3001
    ,但可能是
    3002+
  5. 验证脚本执行:在首次访问应用后,再次检查
    work-tmp/debug/latest/backend.log
    是否有任何错误
  6. 通过查看
    work-tmp/debug/latest/backend.log
    work-tmp/debug/latest/frontend.log
    监控日志
  7. 编辑代码——变更会通过热重载自动生效
  8. 检查日志中的调试输出
快速错误检查:
bash
undefined

Backend errors

后端错误

rg -i "error|exception" work-tmp/debug/latest/backend.log
rg -i "error|exception" work-tmp/debug/latest/backend.log

Frontend console errors

前端控制台错误

rg -i "error" work-tmp/debug/latest/frontend.log
undefined
rg -i "error" work-tmp/debug/latest/frontend.log
undefined

Temporary Playwright Scripts for Screenshots & Testing

用于截图和测试的临时Playwright脚本

For advanced debugging with screenshots or automated UI interaction.
适用于需要截图或自动化UI交互的高级调试场景。

Quick: Playwright CLI

快速方式:Playwright CLI

For simple screenshots and interactions, use
@playwright/cli
(available in frontend devDependencies):
bash
cd frontend
STREAMLIT_APP_URL=http://localhost:3001
yarn playwright-cli open "$STREAMLIT_APP_URL"
yarn playwright-cli screenshot --filename ../work-tmp/debug/screenshot.png --full-page
yarn playwright-cli close
See https://github.com/microsoft/playwright-cli for more commands (
snapshot
,
click
,
fill
, etc.).
对于简单的截图和交互,使用
@playwright/cli
(已包含在前端devDependencies中):
bash
cd frontend
STREAMLIT_APP_URL=http://localhost:3001
yarn playwright-cli open "$STREAMLIT_APP_URL"
yarn playwright-cli screenshot --filename ../work-tmp/debug/screenshot.png --full-page
yarn playwright-cli close
更多命令(
snapshot
click
fill
等)请查看:https://github.com/microsoft/playwright-cli

Custom Scripts

自定义脚本

For complex interactions, create temporary Playwright scripts in
work-tmp/debug/
:
python
undefined
对于复杂交互,在
work-tmp/debug/
中创建临时Playwright脚本:
python
undefined

work-tmp/debug/debug_screenshot.py

work-tmp/debug/debug_screenshot.py

"""Temporary Playwright script for debugging - run against make debug.""" import os from playwright.sync_api import sync_playwright, expect
from e2e_playwright.shared.app_utils import get_text_input, click_button from e2e_playwright.conftest import wait_for_app_loaded, wait_for_app_run
def main(): app_url = os.environ.get("STREAMLIT_APP_URL", "http://localhost:3001") with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1280, "height": 720})
    # Connect to app started with `make debug`
    page.goto(app_url)
    wait_for_app_loaded(page)

    # Interact with the app
    text_input = get_text_input(page, "Name")
    text_input.fill("Test User")
    click_button(page, "Submit")
    wait_for_app_run(page)

    # Verify and screenshot
    expect(page.get_by_text("Hello, Test User")).to_be_visible()
    page.screenshot(path="work-tmp/debug/debug_screenshot.png", full_page=True)
    print("Screenshot saved to work-tmp/debug/debug_screenshot.png")

    browser.close()
if name == "main": main()
undefined
"""Temporary Playwright script for debugging - run against make debug.""" import os from playwright.sync_api import sync_playwright, expect
from e2e_playwright.shared.app_utils import get_text_input, click_button from e2e_playwright.conftest import wait_for_app_loaded, wait_for_app_run
def main(): app_url = os.environ.get("STREAMLIT_APP_URL", "http://localhost:3001") with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1280, "height": 720})
    # 连接到用`make debug`启动的应用
    page.goto(app_url)
    wait_for_app_loaded(page)

    # 与应用交互
    text_input = get_text_input(page, "Name")
    text_input.fill("Test User")
    click_button(page, "Submit")
    wait_for_app_run(page)

    # 验证并截图
    expect(page.get_by_text("Hello, Test User")).to_be_visible()
    page.screenshot(path="work-tmp/debug/debug_screenshot.png", full_page=True)
    print("Screenshot saved to work-tmp/debug/debug_screenshot.png")

    browser.close()
if name == "main": main()
undefined

Running Temporary Scripts

运行临时脚本

Ensure
make debug <app.py>
is running first (start it in a background task if needed). If your
make debug
session is using a non-default port, set
STREAMLIT_APP_URL
accordingly, then run the Playwright script:
bash
STREAMLIT_APP_URL=http://localhost:3001 \
PYTHONPATH=. uv run python work-tmp/debug/debug_screenshot.py
This uses the uv-managed environment with all dependencies (playwright, etc.) and makes
e2e_playwright
importable without path manipulation.
确保
make debug <app.py>
已在运行(如有需要可在后台任务中启动)。如果你的
make debug
会话使用了非默认端口,请相应设置
STREAMLIT_APP_URL
,然后运行Playwright脚本:
bash
STREAMLIT_APP_URL=http://localhost:3001 \
PYTHONPATH=. uv run python work-tmp/debug/debug_screenshot.py
这会使用uv管理的环境(包含所有依赖,如playwright等),并无需路径配置即可导入
e2e_playwright

Available Utilities from e2e_playwright

来自e2e_playwright的可用工具

Element Locators & Interactions (
e2e_playwright.shared.app_utils
): Provides helpers like
get_text_input()
,
get_button()
,
click_button()
,
get_checkbox()
, etc.
Synchronization (
e2e_playwright.conftest
):
  • wait_for_app_loaded(page)
    - wait for initial load
  • wait_for_app_run(page)
    - wait for script execution after interaction
  • wait_until(page, fn, timeout)
    - poll until condition is true
元素定位与交互
e2e_playwright.shared.app_utils
): 提供
get_text_input()
get_button()
click_button()
get_checkbox()
等辅助函数。
同步工具
e2e_playwright.conftest
):
  • wait_for_app_loaded(page)
    - 等待初始加载完成
  • wait_for_app_run(page)
    - 等待交互后的脚本执行完成
  • wait_until(page, fn, timeout)
    - 轮询直到条件满足

Screenshot Best Practices

截图最佳实践

python
undefined
python
undefined

Full page screenshot

全页截图

page.screenshot(path="work-tmp/debug/full.png", full_page=True)
page.screenshot(path="work-tmp/debug/full.png", full_page=True)

Element screenshot

元素截图

element = page.get_by_test_id("stDataFrame") element.screenshot(path="work-tmp/debug/dataframe.png")
undefined
element = page.get_by_test_id("stDataFrame") element.screenshot(path="work-tmp/debug/dataframe.png")
undefined

Troubleshooting

故障排除

Port already in use / multiple sessions:
  • make debug
    will automatically pick a free frontend port (typically in the
    3001-3100
    range) so multiple debug sessions can run simultaneously.
  • Frontend port
    3000
    is reserved for manual
    make frontend-dev
    sessions.
  • If you have a hard requirement for a specific frontend port, you can pin it with
    VITE_PORT=3002 make debug <app.py>
    (last resort).
Hot-reload not working:
  • Backend: Only the app script is watched. Changes to
    lib/streamlit/
    require restarting
    make debug
    .
  • Frontend: Check
    work-tmp/debug/latest/frontend.log
    for Vite errors. TypeScript errors can break HMR.
Playwright script fails to connect:
  • Verify
    make debug
    is running and healthy
  • Check the printed App URL is accessible in the browser
  • Ensure
    wait_for_app_loaded(page)
    is called after
    page.goto()
端口已被占用 / 多个会话:
  • make debug
    会自动选择空闲的前端端口(通常在
    3001-3100
    范围内),因此可以同时运行多个调试会话。
  • 前端端口
    3000
    预留给手动执行
    make frontend-dev
    的会话。
  • 如果你有固定特定前端端口的硬性需求,可以使用
    VITE_PORT=3002 make debug <app.py>
    (这是最后的手段)。
热重载不生效:
  • 后端:仅监控应用脚本。对
    lib/streamlit/
    的修改需要重启
    make debug
  • 前端:检查
    work-tmp/debug/latest/frontend.log
    中的Vite错误。TypeScript错误可能会破坏HMR(模块热替换)。
Playwright脚本无法连接:
  • 验证
    make debug
    是否在运行且状态正常
  • 检查打印的应用URL是否能在浏览器中访问
  • 确保在
    page.goto()
    之后调用了
    wait_for_app_loaded(page)

Cleanup

清理

After debugging is complete, remove temporary scripts and screenshots from
work-tmp/debug/
.
调试完成后,删除
work-tmp/debug/
中的临时脚本和截图。