python︱写markdown一样写网页,代码快速生成web工具:streamlit 缓存(五)

本文深入探讨了Streamlit中的缓存机制,包括@st.cache装饰器的工作原理、不同使用场景及注意事项。通过实例展示了如何有效利用缓存提高Web应用性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列参考:
python︱写markdown一样写网页,代码快速生成web工具:streamlit介绍(一)
python︱写markdown一样写网页,代码快速生成web工具:streamlit 重要组件介绍(二)
python︱写markdown一样写网页,代码快速生成web工具:streamlit 展示组件(三)
python︱写markdown一样写网页,代码快速生成web工具:streamlit lay-out布局(四)
python︱写markdown一样写网页,代码快速生成web工具:streamlit 缓存(五)
python︱写markdown一样写网页,代码快速生成web工具:streamlit 数据探索案例(六)
streamlit + opencv/YOLOv3 快速构建自己的图像目标检测demo网页(七)

github代码链接:mattzheng/streamlit_demo



整个文档可参考:https://docs.streamlit.io/en/stable/caching.html

当您用@st标记一个函数时。缓存装饰器,它告诉Streamlit无论何时调用函数都需要检查以下几件事:

  • The input parameters that you called the function with
  • The value of any external variable used in the function
  • The body of the function
  • The body of any function used inside the cached function

cache在后台操作的步骤为:


For example, when the function expensive_computation(a, b), decorated with @st.cache, is executed with a=2 and b=21, Streamlit does the following:

1 Computes the cache key
    
2 If the key is found in the cache, then:

- Extracts the previously-cached (output, output_hash) tuple.

- Performs an Output Mutation Check, where a fresh hash of the output is computed and compared to the stored output_hash.

    - If the two hashes are different, shows a Cached Object Mutated warning. (Note: Setting allow_output_mutation=True disables this step).

3 If the input key is not found in the cache, then:

- Executes the cached function (i.e. output = expensive_computation(2, 21)).

- Calculates the output_hash from the function’s output.

- Stores key → (output, output_hash) in the cache.

4 Returns the output.

1 不适用cache的方式

比如求指数,如果不缓存,重新刷新一次还是需要重新计算

import streamlit as st
import time

def expensive_computation(a, b):
    time.sleep(2)  # 👈 This makes the function take 2s to run
    return a * b

a = 2
b = 21
res = expensive_computation(a, b)

st.write("Result:", res)

在这里插入图片描述

2 cache

cache能不能被使用得到,可以通过st.write检测

suppress_st_warning可以关闭一些因为缓存还没计算出,带来的报错

  • cache状态下,支持随时修改函数的参数
  • cache状态下,支持任意函数结构改变
@st.cache(suppress_st_warning=True)  # 👈 Changed this
def expensive_computation(a, b):
    # 👇 Added this
    st.write("Cache miss: expensive_computation(", a, ",", b, ") ran")
    time.sleep(2)  # This makes the function take 2s to run
    return a * b

a = 2
b = 21
res = expensive_computation(a, b)

st.write("Result:", res)

在这里插入图片描述

3 cache + 可选项

设置一个slider选项,这种情况会发生:

  • 如果之前没有看到过slider里面的数字,那么就会重新执行
  • 如果有,那么就会直接跳出
  • 另外一种,如果接下来这个web会被多人使用,其他人调用过的,也是没有问题的!

功能强大,就不用自己写cache了,简直神器


@st.cache(suppress_st_warning=True)
def expensive_computation(a, b):
    st.write("Cache miss: expensive_computation(", a, ",", b, ") ran")
    time.sleep(2)  # This makes the function take 2s to run
    return a * b

a = 2
b = st.slider("Pick a number", 0, 10)  # 👈 Changed this
res = expensive_computation(a, b)

st.write("Result:", res)

在这里插入图片描述

4 cache 返回字典型

如果返回字典性,会以json的格式展示,非常方便

同时缓存机制有一个比较大的问题:
- 比如第一次正常执行res['output'] = 1
- 然而,不改变a/b的情况下,再刷新页面一次,因为a/b没变,所以就没有重新计算expensive_computation(a, b)
就会造成res['output'] = "result was manually mutated", 这个时候就有问题,会报错提醒:

CachedObjectMutationWarning: Return value of expensive_computation() was mutated between runs.

所以尽量避免生成值之后的再赋值。

@st.cache(suppress_st_warning=True)
def expensive_computation(a, b):
    st.write("Cache miss: expensive_computation(", a, ",", b, ") ran")
    time.sleep(2)  # This makes the function take 2s to run
    return {"output": a * b}  # 👈 Mutable object

a = 2
b = 21
res = expensive_computation(a, b)

st.write("Result:", res)

res["output"] = "result was manually mutated"  # 👈 Mutated cached value

st.write("Mutated result:", res)

在这里插入图片描述

<think>好的,用户问的是是否可以用Python开发一个程序,运行时用浏览器作为前端界面,后端用Python。嗯,这个问题其实挺常见的,用户可能想要一个基于Web的界面,但后端逻辑用Python来处理。首先,我得确认用户的需求是什么。他们可能希望程序有一个用户友好的界面,而浏览器作为前端比较方便,不需要安装额外的GUI库,跨平台也容易。 接下来,我需要考虑现有的Python框架是否支持这种架构。比如,Flask或Django这些Web框架可以处理后端,但用户希望程序运行时自动打开浏览器,并在本地运行。这时候可能需要用到像Flask的内置服务器,或者使用Brython,不过Brython是在浏览器里跑Python,可能不符合用户的后端需求。 另外,用户提到后端仍然用Python,所以前端和后端之间的通信需要处理。可能需要使用AJAX或者WebSocket来让前端和后端交互。例如,前端通过HTTP请求发送数据到后端,后端处理后再返回结果。 然后,想到一些工具库,比如Eel或PyWebIO。Eel允许用Python作为后端,前端用HTML/CSS/JS,并且自动打开浏览器窗口。PyWebIO则可以直接用Python生成Web界面,适合简单的应用。还有Streamlit,适合数据应用,但可能需要更多的配置。 用户可能的隐藏需求是希望简化部署,不需要复杂的Web服务器配置,或者想要一个轻量级的解决方案。他们可能不太熟悉前端开发,所以希望用Python同时处理后端和生成前端界面。 需要比较这些框架的优缺点,比如Eel的易用性,PyWebIO的简洁性,或者Flask的灵活性。还要考虑是否需要实时更新,比如使用WebSocket还是普通的HTTP请求就够了。 另外,安全性也是一个方面,如果程序只在本地运行,可能不需要考虑太多安全问题,但如果涉及网络,就需要防范一些常见的漏洞。 最后,总结这些信息,给出几个可行的方案,并推荐适合不同场景的工具,帮助用户根据具体需求选择最合适的框架。</think>--- ### **直接回答** 完全可以实现!通过**Python Web框架 + 浏览器前端**的架构,您可以用Python同时控制后端逻辑和浏览器界面。以下是具体实现方案: --- ### **技术方案对比** | 方案 | 核心原理 | 适用场景 | 开发难度 | 维护性 | |-------------------|----------------------------|-----------------------|--------|--------| | **Flask + 自动跳转** | 本地启动Web服务器自动开浏览器 | 需要完整前后端分离 | 中 | 高 | | **Eel 框架** | 封装Chromium与Python通信 | 类桌面应用开发 | 低 | 中 | | **PyWebIO** | 纯Python生成Web界面 | 快速原型/简单工具 | 极低 | 高 | | **Brython** | 浏览器中直接运行Python | 纯浏览器环境 | 中 | 低 | --- ### **推荐方案1:Eel框架(最佳实践)** #### **实现步骤** 1. **安装库** ```bash pip install eel ``` 2. **目录结构** ``` myapp/ ├── main.py # Python后端 └── web/ # 前端资源 ├── index.html ├── style.css └── app.js ``` 3. **Python后端** (`main.py`) ```python import eel # 初始化Eel,指定web文件夹为前端资源目录 eel.init('web') # 暴露Python函数给前端 @eel.expose def process_data(input_text): # 在此处编核心逻辑 return f"Python处理结果: {input_text.upper()}" # 启动Chrome浏览器并打开页面 eel.start('index.html', size=(800, 600)) ``` 4. **HTML前端** (`web/index.html`) ```html <!DOCTYPE html> <html> <head> <title>Python Web App</title> <script src="/eel.js"></script> </head> <body> <input type="text" id="input"> <button onclick="run()">执行</button> <div id="result"></div> <script> async function run() { const input = document.getElementById('input').value; // 调用Python函数 const response = await eel.process_data(input)(); document.getElementById('result').textContent = response; } </script> </body> </html> ``` --- ### **推荐方案2:PyWebIO(极简版)** ```python from pywebio import start_server from pywebio.input import * from pywebio.output import * def main(): # 网页界面 info = input("请输入需要处理的内容") # Python后端处理 processed = info.upper() # 示例处理 # 显示结果 put_markdown(f"## 处理结果\n`{processed}`") if __name__ == '__main__': start_server(main, port=8080, auto_open_webbrowser=True) ``` --- ### **关键技术点** 1. **通信机制** - **Eel**: 通过`eel.expose`双向暴露函数 ```javascript // 前端调用Python eel.python_func()(js_callback) // Python调用前端 eel.js_func()() ``` 2. **打包为EXE** (使用PyInstaller) ```bash pip install pyinstaller pyinstaller --add-data "web;web" --noconsole main.py ``` 3. **跨平台支持** ```python # 强制使用Chrome(解决Edge兼容问题) eel.start(..., mode='chrome') ``` --- ### **实际案例演示** **文件批量处理器**: ```python @eel.expose def batch_rename_files(path, old_str, new_str): # 实际文件操作逻辑 renamed_files = [] for f in Path(path).glob('**/*'): if old_str in f.name: new_name = f.name.replace(old_str, new_str) f.rename(f.parent / new_name) renamed_files.append(new_name) return renamed_files ``` --- ### **性能优化技巧** 1. **WebSocket加速**:在Eel配置中启用 ```python eel.start(..., websocket_origin=None) ``` 2. **多线程处理**: ```python from threading import Thread @eel.expose def long_task(): Thread(target=实际耗时函数).start() ``` 3. **前端缓存**:在HTML中添加manifest文件 --- ### **安全注意事项** 1. **输入过滤**:防止路径遍历攻击 ```python from pathlib import Path def safe_path(user_input): return Path(user_input).resolve().relative_to(Path.cwd()) ``` 2. **CORS配置**:开发时关闭,发布时开启 ```python eel.start(..., options={'cors': 'http://localhost:8080'}) ``` --- ### **扩展方案**:结合Electron 当需要更复杂的前端时: 1. 用Electron构建界面 2. 通过`python-shell`调用Python脚本 3. 使用IPC通信 ```javascript // Electron主进程 const { PythonShell } = require('python-shell'); ipcMain.on('process-data', (event, arg) => { PythonShell.runString('print("Hello from Python")', null, (err, res) => event.reply('reply', res)); }); ``` --- ### **总结建议** - 快速开发选 **PyWebIO** - 桌面应用体验选 **Eel** - 企业级应用选 **Flask + React/Vue** - 特殊需求可用 **FastAPI + WebSocket** 实现实时通信 实际代码示例已托管至GitHub(模拟地址): `https://github.com/example/python-web-gui-template`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值