--- description: globs: alwaysApply: false --- # Python代码执行 本项目使用`uv`在隔离环境中执行Python代码,提供安全可靠的执行环境。以下是Python代码执行的详细流程: ## Python运行器 Python代码通过[PythonRunner](mdc:src/python_runner/python_runner.rs)执行,实现了`RunCode`特性: ```rust pub struct PythonRunner; impl RunCode for PythonRunner { async fn run(&self, code: &str) -> Result { // 实现代码... } async fn run_with_params(&self, code: &str, params: Option) -> Result { // 实现代码... } } ``` ## 依赖解析 Python代码的依赖通过[python_dependencies.rs](mdc:src/python_runner/dependencies/python_dependencies.rs)解析: 1. 使用Pest解析器分析Python代码中的import语句 2. 支持常规import语句和importlib动态导入 3. 提取所有导入的模块名称 ```rust pub fn parse_import(python_code: &str) -> Result> { // 使用Pest解析器分析Python代码 let pairs = ImportParser::parse(Rule::file, &input)?; // 提取模块名称 let mut imported_modules = Vec::new(); // 处理各种import语句... Ok(imported_modules) } ``` ## 代码准备 Python代码在执行前需要进行包装,添加日志捕获和函数执行逻辑: ```rust fn prepare_python_code(&self, code: &str, show_logs: bool) -> String { // 创建包装代码,包括: // 1. 日志捕获 // 2. 参数解析 // 3. 执行handler或main函数 // 4. 结果格式化 } ``` 包装代码主要功能: 1. 捕获标准输出作为日志 2. 从环境变量`INPUT_JSON`解析参数 3. 优先执行`handler`函数,如果不存在则执行`main`函数 4. 将执行结果和日志格式化为JSON ## 参数传递 参数通过环境变量`INPUT_JSON`传递给Python脚本: ```rust // 将参数序列化为JSON字符串 let params_json = match params { Some(p) => serde_json::to_string(&p)?, None => "{}".to_string(), }; // 通过环境变量传递参数 execute_command.env("INPUT_JSON", ¶ms_json); ``` 在Python脚本中,参数通过以下方式获取: ```python # 从环境变量获取输入参数 args = {} try: input_json = os.environ.get('INPUT_JSON') if input_json: args = json.loads(input_json) except Exception as e: print(f"解析输入参数失败: {e}") ``` ## 执行流程 1. 计算代码哈希值,检查缓存 2. 如果缓存存在,直接使用;否则: - 分析代码依赖 - 准备包装后的代码 - 保存到缓存 3. 使用`uv`命令在隔离环境中执行代码: ```rust let mut execute_command = Command::new("uv"); execute_command .arg("run") .arg("-s") // 明确指定作为脚本运行 .arg("--isolated") // 在隔离环境中运行 .arg("-p") .arg("python3") // 指定Python解释器 .env("INPUT_JSON", ¶ms_json) // 通过环境变量传递参数 .arg(&temp_path) ``` 4. 解析执行结果,提取日志和返回值 ## 结果处理 执行结果通过JSON格式返回,包含三个字段: - `logs`: 执行过程中的日志数组 - `result`: 执行结果(可能是字符串、数字、布尔值、对象等) - `error`: 执行错误(如果有) ```json { "logs": ["日志1", "日志2", ...], "result": "执行结果", "error": null } ``` ## 支持的返回类型 Python脚本可以返回多种类型的值: 1. 字符串 2. 数字 3. 布尔值 4. 列表/数组 5. 字典/对象 6. None/null 所有复杂类型(列表、字典)都会被序列化为JSON字符串。