mxivideo/docs/python_executor_progress.md

292 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🚀 通用Python执行器进度支持系统
一个完全重构的通用Python执行器支持实时进度回调、JSON-RPC通信和简化的命令创建。
## ✨ 新特性
- 🎯 **通用进度支持**:一次实现,到处使用
- 🔧 **简化的API**:多种便利函数和宏
- 📊 **实时进度更新**支持Tauri事件和自定义回调
- 🛠️ **命令构建器**简化Python命令构造
- 📝 **丰富的示例**:涵盖各种使用场景
## 功能特性
- ✅ 支持多种Python命令 (python, python3, py)
- ✅ UTF-8编码处理
- ✅ 并发stdout/stderr读取
- ✅ JSON-RPC消息解析
- ✅ 实时进度回调
- ✅ Tauri事件发射
- ✅ 超时处理
- ✅ 错误处理
## 🎯 核心API
### 1. 通用进度执行函数
```rust
// 最通用的函数 - 推荐使用
execute_python_action_with_progress(
app: AppHandle,
module: &str, // Python模块路径
action: &str, // 要执行的动作
params: &[(&str, &str)], // 参数键值对
event_name: &str, // 前端事件名称
config: Option<PythonExecutorConfig>
) -> Result<String, String>
```
### 2. 便利函数
```rust
// Tauri事件进度推荐用于前端集成
execute_python_with_events(app, &args, config, "event-name")
// 函数回调进度(用于自定义处理)
execute_python_with_callback(app, &args, config, callback)
// 基本执行(无进度)
execute_python_command(app, &args, config)
```
### 3. 宏支持
```rust
// 简单命令宏
python_action_command! {
name: my_simple_command,
module: "python_core.my_module",
action: "my_action",
event: "my-progress-event"
}
```
## 📋 使用方法
### 1. 基本用法(无进度)
```rust
use crate::python_executor::execute_python_command;
#[tauri::command]
pub async fn my_command(app: AppHandle) -> Result<String, String> {
let args = vec![
"-m".to_string(),
"my_python_module".to_string(),
"--action".to_string(),
"do_something".to_string(),
];
execute_python_command(app, &args, None).await
}
```
### 2. 使用Tauri事件进度回调
```rust
use crate::python_executor::execute_python_with_events;
#[tauri::command]
pub async fn my_command_with_progress(app: AppHandle) -> Result<String, String> {
let args = vec![
"-m".to_string(),
"my_python_module".to_string(),
"--action".to_string(),
"long_running_task".to_string(),
];
// 进度将通过 "my-task-progress" 事件发送到前端
execute_python_with_events(app, &args, None, "my-task-progress").await
}
```
### 3. 使用函数回调
```rust
use crate::python_executor::{execute_python_with_callback, PythonProgress};
#[tauri::command]
pub async fn my_command_with_callback(app: AppHandle) -> Result<String, String> {
let args = vec![
"-m".to_string(),
"my_python_module".to_string(),
"--action".to_string(),
"process_data".to_string(),
];
// 自定义进度处理
let progress_callback = |progress: PythonProgress| {
println!("Progress: {}% - {}", progress.progress, progress.message);
// 可以在这里添加自定义逻辑,如数据库记录、日志等
};
execute_python_with_callback(app, &args, None, progress_callback).await
}
```
### 4. 高级用法(自定义回调)
```rust
use crate::python_executor::{execute_python_command_with_progress, ProgressCallback, PythonProgress};
struct CustomProgressHandler {
task_id: String,
}
impl ProgressCallback for CustomProgressHandler {
fn on_progress(&self, progress: PythonProgress) {
// 自定义进度处理逻辑
println!("Task {}: {}% - {}", self.task_id, progress.progress, progress.message);
// 可以发送到数据库、文件、其他服务等
if progress.step == "complete" {
println!("Task {} completed!", self.task_id);
}
}
}
#[tauri::command]
pub async fn my_advanced_command(app: AppHandle, task_id: String) -> Result<String, String> {
let args = vec![
"-m".to_string(),
"my_python_module".to_string(),
"--task-id".to_string(),
task_id.clone(),
];
let progress_handler = CustomProgressHandler { task_id };
execute_python_command_with_progress(app, &args, None, Some(progress_handler)).await
}
```
## Python端实现
Python脚本需要使用JSON-RPC协议发送进度信息
```python
from python_core.utils.jsonrpc import create_response_handler, create_progress_reporter
def my_long_running_task():
rpc = create_response_handler("task_id")
progress = create_progress_reporter()
try:
# 报告开始
progress.step("start", "开始处理任务...")
# 处理步骤1
progress.report("step1", 25.0, "正在处理步骤1...")
# ... 实际处理逻辑 ...
# 处理步骤2
progress.report("step2", 50.0, "正在处理步骤2...")
# ... 实际处理逻辑 ...
# 处理步骤3
progress.report("step3", 75.0, "正在处理步骤3...")
# ... 实际处理逻辑 ...
# 完成
progress.complete("任务完成!")
# 发送最终结果
result = {
"status": True,
"message": "任务成功完成",
"data": {...}
}
rpc.success(result)
except Exception as e:
progress.error(f"任务失败: {str(e)}")
rpc.error(-32603, "任务执行失败", str(e))
if __name__ == "__main__":
my_long_running_task()
```
## 前端使用
```typescript
import { listen } from '@tauri-apps/api/event'
// 监听进度事件
const unlisten = await listen('my-task-progress', (event) => {
const progress = event.payload as {
step: string
progress: number
message: string
details?: any
timestamp: number
}
console.log(`Progress: ${progress.progress}% - ${progress.message}`)
// 更新UI
updateProgressBar(progress.progress)
updateStatusMessage(progress.message)
})
// 执行命令
try {
const result = await invoke('my_command_with_progress')
console.log('Task completed:', result)
} finally {
unlisten() // 清理监听器
}
```
## 进度数据结构
```rust
pub struct PythonProgress {
pub step: String, // 当前步骤名称
pub progress: f64, // 进度百分比 (0-100, -1表示不确定)
pub message: String, // 进度消息
pub details: Option<serde_json::Value>, // 额外详情
pub timestamp: f64, // 时间戳
}
```
## 配置选项
```rust
pub struct PythonExecutorConfig {
pub timeout_seconds: u64, // 超时时间(秒)
pub working_directory: Option<PathBuf>, // 工作目录
}
// 默认配置10分钟超时当前目录
let config = PythonExecutorConfig::default();
// 自定义配置
let config = PythonExecutorConfig {
timeout_seconds: 1800, // 30分钟
working_directory: Some("/path/to/workdir".into()),
};
```
## 最佳实践
1. **选择合适的回调方式**
- 简单任务:使用 `execute_python_command`
- 需要前端进度显示:使用 `execute_python_with_events`
- 需要自定义处理:使用 `execute_python_with_callback`
2. **Python端进度报告**
- 使用有意义的步骤名称
- 提供清晰的进度消息
- 合理设置进度百分比
- 在关键节点报告进度
3. **错误处理**
- Python端使用try-catch包装
- 通过JSON-RPC发送错误信息
- Rust端处理超时和进程错误
4. **性能考虑**
- 不要过于频繁地报告进度
- 避免在进度回调中执行耗时操作
- 合理设置超时时间