refactor: 简化错误处理,直接展示原始API返回信息
- 移除 base_client.py 中针对各HTTP状态码的中文友好提示 - 移除 gemini_client.py 和节点中的重复错误打印 - 关闭调试日志和请求体日志输出(DEBUG_LOG_ENABLED=False) - 保留跳过错误功能但默认关闭 - 错误仅通过ComfyUI异常机制统一展示一次 Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
+1
-90
@@ -178,96 +178,7 @@ class BaseAPIClient(ABC):
|
|||||||
|
|
||||||
if response.status != 200:
|
if response.status != 200:
|
||||||
error_text = await response.text()
|
error_text = await response.text()
|
||||||
|
raise RuntimeError(error_text)
|
||||||
# 尝试解析 JSON 错误信息,提取关键内容
|
|
||||||
error_message = error_text
|
|
||||||
try:
|
|
||||||
error_json = json.loads(error_text)
|
|
||||||
# 尝试从多个常见位置提取错误信息
|
|
||||||
if "error" in error_json:
|
|
||||||
if isinstance(error_json["error"], dict):
|
|
||||||
error_message = error_json["error"].get("message", error_text)
|
|
||||||
else:
|
|
||||||
error_message = str(error_json["error"])
|
|
||||||
elif "message" in error_json:
|
|
||||||
error_message = error_json["message"]
|
|
||||||
except:
|
|
||||||
# 如果不是 JSON,使用原始文本
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 针对常见错误状态码提供友好提示
|
|
||||||
if response.status == 400:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"请求参数错误 (400 Bad Request)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 检查 API 密钥是否有效\n"
|
|
||||||
f" - 确认请求参数格式正确"
|
|
||||||
)
|
|
||||||
elif response.status == 401:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"认证失败 (401 Unauthorized)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 检查 API 密钥是否正确\n"
|
|
||||||
f" - 确认 API 密钥是否过期"
|
|
||||||
)
|
|
||||||
elif response.status == 403:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"权限不足 (403 Forbidden)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 检查 API 密钥权限\n"
|
|
||||||
f" - 确认账户余额充足"
|
|
||||||
)
|
|
||||||
elif response.status == 404:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"端点不存在 (404 Not Found)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 检查模型名称是否正确\n"
|
|
||||||
f" - 使用其他可用模型"
|
|
||||||
)
|
|
||||||
elif response.status == 429:
|
|
||||||
custom = self.get_http_error_message(429, error_message)
|
|
||||||
if custom is not None:
|
|
||||||
raise RuntimeError(custom)
|
|
||||||
raise RuntimeError(
|
|
||||||
f"请求频率超限 (429 Too Many Requests)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 等待一段时间后重试\n"
|
|
||||||
f" - 检查 API 配额是否充足"
|
|
||||||
)
|
|
||||||
elif response.status == 503:
|
|
||||||
custom = self.get_http_error_message(503, error_message)
|
|
||||||
if custom is not None:
|
|
||||||
raise RuntimeError(custom)
|
|
||||||
raise RuntimeError(
|
|
||||||
f"服务暂时不可用 (503 Service Unavailable)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 稍后重试\n"
|
|
||||||
f" - 尝试使用其他模型"
|
|
||||||
)
|
|
||||||
elif response.status == 504:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"API 请求超时 (504 Gateway Timeout)\n"
|
|
||||||
f"API 返回错误:{error_message}\n"
|
|
||||||
f"建议:\n"
|
|
||||||
f" - 尝试使用其他模型\n"
|
|
||||||
f" - 稍后重试\n"
|
|
||||||
f" - 降低分辨率或减少输入图像数量"
|
|
||||||
)
|
|
||||||
elif response.status == 502:
|
|
||||||
raise RuntimeError(
|
|
||||||
"糟糕!请求到上游时遇到超时或过载!别担心,过会儿再次点击运行即可!"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"API 请求失败 (状态码: {response.status})\n"
|
|
||||||
f"API 返回错误:{error_message}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 接收响应体
|
# 接收响应体
|
||||||
wait_start = time.time()
|
wait_start = time.time()
|
||||||
|
|||||||
@@ -518,9 +518,6 @@ class GeminiAPIClient(BaseAPIClient):
|
|||||||
try:
|
try:
|
||||||
response = await self.request_async(endpoint, request_body, session)
|
response = await self.request_async(endpoint, request_body, session)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
request_time = time.time() - request_start
|
|
||||||
error_first_line = str(e).split('\n')[0]
|
|
||||||
print(f"{task_prefix} 请求 {size_str} → API {request_time:.1f}s → 失败: {error_first_line} ✗")
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
request_time = time.time() - request_start
|
request_time = time.time() - request_start
|
||||||
@@ -720,8 +717,6 @@ class GeminiAPIClient(BaseAPIClient):
|
|||||||
if progress_callback:
|
if progress_callback:
|
||||||
progress_callback(completed, batch_size, False, error_msg)
|
progress_callback(completed, batch_size, False, error_msg)
|
||||||
|
|
||||||
print(f"GeminiClient: 任务 {completed}/{batch_size} 失败 ✗")
|
|
||||||
|
|
||||||
# 当前批次完成后,立即清理内存
|
# 当前批次完成后,立即清理内存
|
||||||
if batch_images:
|
if batch_images:
|
||||||
print(f"GeminiClient: 第 {batch_idx + 1} 批完成,生成 {len(batch_images)} 张图片")
|
print(f"GeminiClient: 第 {batch_idx + 1} 批完成,生成 {len(batch_images)} 张图片")
|
||||||
|
|||||||
@@ -704,18 +704,6 @@ class BatchNanoBananaPro:
|
|||||||
print(f"BatchNanoBananaPro: 任务 {completed}/{total_tasks} 成功 ✓")
|
print(f"BatchNanoBananaPro: 任务 {completed}/{total_tasks} 成功 ✓")
|
||||||
else:
|
else:
|
||||||
fail_count += 1
|
fail_count += 1
|
||||||
# 打印完整错误信息(用于排查问题)
|
|
||||||
error_msg = result_data.get("error", "未知错误") if result_data else "未知错误"
|
|
||||||
print(f"BatchNanoBananaPro: 任务 {completed}/{total_tasks} 失败 ✗")
|
|
||||||
print(f"=" * 80)
|
|
||||||
print(f"🔍 【原始报错信息展示】")
|
|
||||||
print(f"=" * 80)
|
|
||||||
print(f"任务编号: {completed}/{total_tasks}")
|
|
||||||
print(f"失败时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
||||||
print(f"-" * 80)
|
|
||||||
print(f"错误详情:")
|
|
||||||
print(error_msg)
|
|
||||||
print(f"=" * 80)
|
|
||||||
|
|
||||||
# 更新 ComfyUI 原生进度条
|
# 更新 ComfyUI 原生进度条
|
||||||
if pbar is not None:
|
if pbar is not None:
|
||||||
@@ -993,7 +981,6 @@ class BatchNanoBananaPro:
|
|||||||
print("BatchNanoBananaPro: 任务执行超时(1小时)")
|
print("BatchNanoBananaPro: 任务执行超时(1小时)")
|
||||||
raise RuntimeError("任务执行超时,请减少任务数量或检查网络连接")
|
raise RuntimeError("任务执行超时,请减少任务数量或检查网络连接")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"BatchNanoBananaPro: 任务执行失败: {str(e)}")
|
|
||||||
# 即使失败,也尝试返回部分结果
|
# 即使失败,也尝试返回部分结果
|
||||||
if 'all_saved_files' in locals():
|
if 'all_saved_files' in locals():
|
||||||
print(f"BatchNanoBananaPro: 部分保存的图片: {len(all_saved_files)} 张")
|
print(f"BatchNanoBananaPro: 部分保存的图片: {len(all_saved_files)} 张")
|
||||||
@@ -1091,35 +1078,25 @@ class BatchNanoBananaPro:
|
|||||||
if str(e) == "未授权!":
|
if str(e) == "未授权!":
|
||||||
print("请联系作者授权后方可使用!")
|
print("请联系作者授权后方可使用!")
|
||||||
raise ValueError("未授权!") from None
|
raise ValueError("未授权!") from None
|
||||||
else:
|
|
||||||
# 用户输入错误 - 打印完整错误信息
|
|
||||||
error_msg = str(e)
|
|
||||||
print(f"BatchNanoBananaPro: ❌ {error_msg}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise ValueError(error_msg) from None
|
raise ValueError(str(e)) from None
|
||||||
|
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
# 打印完整错误信息
|
|
||||||
error_full = str(e)
|
|
||||||
print(f"BatchNanoBananaPro: ❌ {error_full}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise RuntimeError(error_full) from None
|
raise RuntimeError(str(e)) from None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 其他未知错误 - 打印完整错误信息
|
|
||||||
error_msg = str(e)
|
|
||||||
print(f"BatchNanoBananaPro: ❌ {error_msg}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("BatchNanoBananaPro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise type(e)(error_msg) from None
|
raise type(e)(str(e)) from None
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# 查询余额
|
# 查询余额
|
||||||
|
|||||||
@@ -52,10 +52,10 @@ except ImportError:
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# 是否启用调试日志(打印完整的 API 响应内容)
|
# 是否启用调试日志(打印完整的 API 响应内容)
|
||||||
# 设置为 True 以启用调试日志,False 以禁用
|
# 设置为 True 以启用调试日志,False 以禁用
|
||||||
DEBUG_LOG_ENABLED = True
|
DEBUG_LOG_ENABLED = False
|
||||||
# 是否启用请求体日志(打印发送给 API 的请求体,base64 图片数据将自动截断)
|
# 是否启用请求体日志(打印发送给 API 的请求体,base64 图片数据将自动截断)
|
||||||
# 设置为 True 以启用请求体日志,False 以禁用
|
# 设置为 True 以启用请求体日志,False 以禁用
|
||||||
REQUEST_LOG_ENABLED = True
|
REQUEST_LOG_ENABLED = False
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
_NODE = "Nano Banana Pro"
|
_NODE = "Nano Banana Pro"
|
||||||
@@ -605,12 +605,6 @@ class NanoBananaPro:
|
|||||||
print(f"Nano Banana Pro: 任务 {current}/{total} 成功 ✓")
|
print(f"Nano Banana Pro: 任务 {current}/{total} 成功 ✓")
|
||||||
else:
|
else:
|
||||||
fail_count += 1
|
fail_count += 1
|
||||||
# 打印完整的错误信息(用于排查问题)
|
|
||||||
if error_msg:
|
|
||||||
print(f"Nano Banana Pro: 任务 {current}/{total} 失败 ✗")
|
|
||||||
print(f"原始错误详情:\n{error_msg}")
|
|
||||||
else:
|
|
||||||
print(f"Nano Banana Pro: 任务 {current}/{total} 失败 ✗")
|
|
||||||
|
|
||||||
# 更新 ComfyUI 原生进度条
|
# 更新 ComfyUI 原生进度条
|
||||||
if pbar is not None:
|
if pbar is not None:
|
||||||
@@ -875,35 +869,25 @@ class NanoBananaPro:
|
|||||||
if str(e) == "未授权!":
|
if str(e) == "未授权!":
|
||||||
print("请联系作者授权后方可使用!")
|
print("请联系作者授权后方可使用!")
|
||||||
raise ValueError("未授权!") from None
|
raise ValueError("未授权!") from None
|
||||||
else:
|
|
||||||
# 用户输入错误 - 打印完整错误信息
|
|
||||||
error_msg = str(e)
|
|
||||||
print(f"Nano Banana Pro: ❌ {error_msg}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise ValueError(error_msg) from None
|
raise ValueError(str(e)) from None
|
||||||
|
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
# 打印完整错误信息
|
|
||||||
error_full = str(e)
|
|
||||||
print(f"Nano Banana Pro: ❌ {error_full}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise RuntimeError(error_full) from None
|
raise RuntimeError(str(e)) from None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 其他未知错误 - 打印完整错误信息
|
|
||||||
error_msg = str(e)
|
|
||||||
print(f"Nano Banana Pro: ❌ {error_msg}")
|
|
||||||
if 跳过错误:
|
if 跳过错误:
|
||||||
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
print("Nano Banana Pro: ⚠️ 跳过错误已开启,返回占位图继续执行队列")
|
||||||
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
placeholder = Image.new('RGB', (512, 512), color=(128, 128, 128))
|
||||||
return (pil_to_tensor([placeholder]),)
|
return (pil_to_tensor([placeholder]),)
|
||||||
raise type(e)(error_msg) from None
|
raise type(e)(str(e)) from None
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# 查询余额
|
# 查询余额
|
||||||
|
|||||||
Reference in New Issue
Block a user