debugging-streamlit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDebugging Streamlit Apps
调试Streamlit应用
Quick Start
快速开始
bash
make debug my_app.pyThis starts both backend (Streamlit/Python) and frontend (Vite/React) with hot-reload. The app URL is printed on startup (default ; is reserved for manual ; it may use if other debug sessions are running). Avoid pinning unless you have a specific hard requirement (last resort).
http://localhost:30013000make frontend-dev3002+VITE_PORTHot-reload behavior:
- Frontend: Changes to code are applied within seconds.
frontend/ - Backend: Only changes to the app script trigger a rerun. Changes to the Streamlit library itself () require restarting
lib/streamlit/.make debug
bash
make debug my_app.py这会启动带热重载功能的后端(Streamlit/Python)和前端(Vite/React)服务。启动时会打印应用URL(默认是;端口预留给手动执行;如果有其他调试会话在运行,可能会使用端口)。除非有特定的硬性需求,否则不要固定(这是最后的手段)。
http://localhost:30013000make frontend-dev3002+VITE_PORT热重载行为:
- 前端:对目录下代码的变更会在数秒内生效。
frontend/ - 后端:只有对应用脚本的变更会触发重新运行。对Streamlit库本身()的修改需要重启
lib/streamlit/。make debug
Log Files
日志文件
Each run writes logs to a per-session directory under and updates to point at the most recent session.
Because is a symlink, it can move if multiple debug sessions are starting/stopping concurrently—prefer using the session directory path printed by when you need stable log references.
You can find the exact session directory in the startup output under the section.
make debugwork-tmp/debug/work-tmp/debug/latest/latest/*make debugmake debugLog files| File | Content |
|---|---|
| Python |
| Browser |
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 to search for specific patterns:
rgbash
undefined每次运行都会将日志写入下的会话专属目录,并更新指向最近的会话。
由于是一个符号链接,当多个调试会话同时启动/停止时,它可能会移动——当你需要稳定的日志引用时,优先使用启动输出中打印的会话目录路径。
你可以在启动输出的部分找到确切的会话目录。
make debugwork-tmp/debug/work-tmp/debug/latest/latest/*make debugmake debugLog files| 文件 | 内容 |
|---|---|
| Python |
| 浏览器 |
日志会在每次会话开始时清空,并在退出后保留以便事后分析。
日志大小警告: 在长时间的调试会话中,日志可能会变得很大。不要直接读取整个日志文件,而是使用搜索特定模式:
rgbash
undefinedSearch 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 output appears in (or the current session's file).
console.log()work-tmp/debug/latest/frontend.logfrontend.log后端(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.logfrontend.logWorkflow
工作流
- Create or use a test script in (e.g.,
work-tmp/debug/)work-tmp/debug/test_feature.py - Run
make debug work-tmp/debug/test_feature.py - Verify startup: Check for
work-tmp/debug/latest/backend.log/ErrorandExceptionfor console errors to ensure both servers started correctlywork-tmp/debug/latest/frontend.log - Access the printed App URL in your browser (default , but it may be
http://localhost:3001)3002+ - Verify script execution: Check again for any errors after the first app access
work-tmp/debug/latest/backend.log - Monitor logs by inspecting and
work-tmp/debug/latest/backend.logwork-tmp/debug/latest/frontend.log - Edit code - changes apply automatically via hot-reload
- Check logs for debug output
Quick error check:
bash
undefined- 在中创建或使用测试脚本(例如
work-tmp/debug/)work-tmp/debug/test_feature.py - 运行
make debug work-tmp/debug/test_feature.py - 验证启动状态:检查中的
work-tmp/debug/latest/backend.log/Error,以及Exception中的控制台错误,确保两个服务都正常启动work-tmp/debug/latest/frontend.log - 在浏览器中访问打印的应用URL(默认是,但可能是
http://localhost:3001)3002+ - 验证脚本执行:在首次访问应用后,再次检查是否有任何错误
work-tmp/debug/latest/backend.log - 通过查看和
work-tmp/debug/latest/backend.log监控日志work-tmp/debug/latest/frontend.log - 编辑代码——变更会通过热重载自动生效
- 检查日志中的调试输出
快速错误检查:
bash
undefinedBackend 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
undefinedrg -i "error" work-tmp/debug/latest/frontend.log
undefinedTemporary 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 (available in frontend devDependencies):
@playwright/clibash
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对于简单的截图和交互,使用(已包含在前端devDependencies中):
@playwright/clibash
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 closeCustom Scripts
自定义脚本
For complex interactions, create temporary Playwright scripts in :
work-tmp/debug/python
undefined对于复杂交互,在中创建临时Playwright脚本:
work-tmp/debug/python
undefinedwork-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()
undefinedRunning Temporary Scripts
运行临时脚本
Ensure is running first (start it in a background task if needed). If your session is using a non-default port, set accordingly, then run the Playwright script:
make debug <app.py>make debugSTREAMLIT_APP_URLbash
STREAMLIT_APP_URL=http://localhost:3001 \
PYTHONPATH=. uv run python work-tmp/debug/debug_screenshot.pyThis uses the uv-managed environment with all dependencies (playwright, etc.) and makes importable without path manipulation.
e2e_playwright确保已在运行(如有需要可在后台任务中启动)。如果你的会话使用了非默认端口,请相应设置,然后运行Playwright脚本:
make debug <app.py>make debugSTREAMLIT_APP_URLbash
STREAMLIT_APP_URL=http://localhost:3001 \
PYTHONPATH=. uv run python work-tmp/debug/debug_screenshot.py这会使用uv管理的环境(包含所有依赖,如playwright等),并无需路径配置即可导入。
e2e_playwrightAvailable Utilities from e2e_playwright
来自e2e_playwright的可用工具
Element Locators & Interactions ():
Provides helpers like , , , , etc.
e2e_playwright.shared.app_utilsget_text_input()get_button()click_button()get_checkbox()Synchronization ():
e2e_playwright.conftest- - wait for initial load
wait_for_app_loaded(page) - - wait for script execution after interaction
wait_for_app_run(page) - - poll until condition is true
wait_until(page, fn, timeout)
Playwright API Reference: https://playwright.dev/python/docs/api/class-playwright
元素定位与交互():
提供、、、等辅助函数。
e2e_playwright.shared.app_utilsget_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)
Playwright API参考:https://playwright.dev/python/docs/api/class-playwright
Screenshot Best Practices
截图最佳实践
python
undefinedpython
undefinedFull 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")
undefinedelement = page.get_by_test_id("stDataFrame")
element.screenshot(path="work-tmp/debug/dataframe.png")
undefinedTroubleshooting
故障排除
Port already in use / multiple sessions:
- will automatically pick a free frontend port (typically in the
make debugrange) so multiple debug sessions can run simultaneously.3001-3100 - Frontend port is reserved for manual
3000sessions.make frontend-dev - If you have a hard requirement for a specific frontend port, you can pin it with (last resort).
VITE_PORT=3002 make debug <app.py>
Hot-reload not working:
- Backend: Only the app script is watched. Changes to require restarting
lib/streamlit/.make debug - Frontend: Check for Vite errors. TypeScript errors can break HMR.
work-tmp/debug/latest/frontend.log
Playwright script fails to connect:
- Verify is running and healthy
make debug - Check the printed App URL is accessible in the browser
- Ensure is called after
wait_for_app_loaded(page)page.goto()
端口已被占用 / 多个会话:
- 会自动选择空闲的前端端口(通常在
make debug范围内),因此可以同时运行多个调试会话。3001-3100 - 前端端口预留给手动执行
3000的会话。make frontend-dev - 如果你有固定特定前端端口的硬性需求,可以使用(这是最后的手段)。
VITE_PORT=3002 make debug <app.py>
热重载不生效:
- 后端:仅监控应用脚本。对的修改需要重启
lib/streamlit/。make debug - 前端:检查中的Vite错误。TypeScript错误可能会破坏HMR(模块热替换)。
work-tmp/debug/latest/frontend.log
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/