Files
cmshoppe/docs/tasks/T-561.md
T

53 lines
3.7 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.
---
id: T-561
title: cmhub curl 下载隐藏 Windows 黑窗
phase: 7
deps: [T-548, T-524]
status: DONE
created: 2026-07-08
---
## 问题 / 背景
T-548 后,②AI生成在 Windows 下默认优先调用系统 `curl.exe` 下载 cmhub 返回的 `image_url`,用于绕过系统代理并提升图片下载速度。实际打包运行时,用户看到每次 curl 下载图片都会弹出黑色控制台窗口,持续几秒后消失。
根因:`app/ai.py` 的 `_download_cmhub_image_with_curl()` 使用 `subprocess.run([...], shell=False)` 启动系统 `curl.exe`,并已把 `stdout/stderr` pipe 住,但没有设置 Windows 隐藏窗口参数。打包后的 PySide6 程序是 GUI 进程,从 GUI 进程启动控制台程序 `curl.exe` 时,Windows 会为子进程创建可见控制台窗口;下载耗时几秒,黑窗就停留几秒。
## 方案
1. **只隐藏 curl 子进程窗口**
- 在 `app/ai.py` 增加 Windows 专用 helper,例如 `_subprocess_hidden_window_kwargs()`。
- 当 `os.name == "nt"` 时,优先给 `subprocess.run()` 传 `creationflags=subprocess.CREATE_NO_WINDOW`。
- 如需兼容环境没有该常量,兜底使用 `subprocess.STARTUPINFO()` + `STARTF_USESHOWWINDOW` + `SW_HIDE`。
- 非 Windows 返回空 dict,保持原逻辑。
2. **保持安全和下载语义不变**
- 仍使用 `shell=False`。
- 仍通过 `-K <临时配置文件>` 传 URL,避免 `image_url` 出现在进程命令行。
- 仍保留 `--silent`、`--show-error`、`--noproxy "*"`、超时、大小上限和失败回退 requests。
- 不把完整 URL、token、API Key 写入日志。
3. **测试**
- 更新 `tests/test_ai.py`,覆盖 Windows 分支下 `subprocess.run()` 收到隐藏窗口参数。
- 保留现有 curl 参数测试:URL 不在 argv、`shell=False`、`--noproxy`、超时、大小上限。
- 非 Windows 分支不强加隐藏窗口参数,避免影响 CI/Linux/macOS。
## 验收要点
- 打包版 ②AI生成用 curl 下载 cmhub 图片时,不再弹出黑色控制台窗口。
- curl 下载仍优先使用系统 curl,失败仍可回退 requests。
- `image_url` 仍不出现在 `subprocess.run()` 的 argv 中。
- 不改 cmhub 生文/生图 API、下载并发、DB、Excel、Shopee/CDP。
- `python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`py -3.10 -m unittest discover -s tests`、`git diff --check` 通过。
## 边界(不改什么)
只改 `app/ai.py` 的 curl 子进程启动参数和对应测试;不改 `ai.cmhub.download_with_curl` 配置 schema、不改系统 curl 检测、不改 requests fallback、不改图片保存 JPEG 逻辑、不改 GUI、DB、Excel、Shopee/CDP。
## 执行记录
- 2026-07-08:`app/ai.py` 新增 `_subprocess_hidden_window_kwargs()`,Windows 下优先使用 `subprocess.CREATE_NO_WINDOW` 隐藏 curl 子进程控制台窗口;缺少该常量时兜底 `STARTUPINFO + STARTF_USESHOWWINDOW + SW_HIDE`;非 Windows 返回空参数。
- 2026-07-08:`_download_cmhub_image_with_curl()` 调用 `subprocess.run()` 时传入隐藏窗口 kwargs,保留 `shell=False`、`-K` 临时配置文件、`--noproxy`、超时、大小上限、stderr/stdout 捕获和 requests fallback 语义。
- 2026-07-08:更新 `tests/test_ai.py`,覆盖 Windows curl 调用携带隐藏窗口参数、URL 不在 argv、`shell=False` 保持,以及非 Windows 不加隐藏窗口参数。
- 验证通过:`py -3.10 -m unittest tests.test_ai.AITests.test_cmhub_image_download_uses_curl_without_url_in_argv tests.test_ai.AITests.test_cmhub_curl_hidden_window_kwargs_are_windows_only tests.test_ai.AITests.test_cmhub_image_download_falls_back_to_requests_when_curl_fails tests.test_ai.AITests.test_cmhub_image_download_auto_without_curl_uses_requests`、`python -m ruff check app tests main.py`。