修复EasyOCR CUDA OOM冻结+时间戳day=0崩溃+OCR图片分目录img/raw+processed
- 冻结根因: CUDA OOM后worker不退出, 损坏context持续占显存, 父进程不杀子进程 反复发图→线程堆积+显存耗尽→桌面冻结 - worker: readtext CUDA/kernel错误→立即退出释放显存(faulerhandler已有兜底) - 父进程: 收到CUDA错误→立即杀子进程+30s冷却; 连续2次CUDA错误→EASYOCR_FORCE_CPU=1 强制CPU模式启动(显存不足降级防冻结) - 时间戳day=0崩溃: _is_timestamp_old跨午夜用replace(day-1), 每月1号day=1→day=0 抛ValueError day is out of range for month→微信OCR整轮失败; 改用timedelta(days=±1) - OCR调试图片回源码目录: img/raw(原图PNG) + img/processed(处理后JPG) 分目录存储 - 崩溃日志回源码根 easyocr_crash.log (不写%LOCALAPPDATA%) - _clean_old_ocr_debug 默认 keep=20 (回退上一轮激进keep=6) - .gitignore: 忽略 img/ 与 worker_stderr/stdout.txt
This commit is contained in:
+12
-10
@@ -18,18 +18,12 @@ import os
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
# ── 崩溃日志文件:写入 %LOCALAPPDATA%/windowmsgbot/,避开源码目录(防 360 误报 + 父进程方便取) ──
|
||||
# ── 崩溃日志文件:写入源码目录根(easyocr_crash.log),统一管理、便于父进程读取 ──
|
||||
def _get_crash_log_path() -> str:
|
||||
try:
|
||||
local = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA")
|
||||
base = os.path.join(local, "windowmsgbot") if local \
|
||||
else os.path.join(os.path.expanduser("~"), "windowmsgbot")
|
||||
except Exception:
|
||||
base = os.path.dirname(os.path.abspath(__file__))
|
||||
try:
|
||||
os.makedirs(base, exist_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
base = "."
|
||||
return os.path.join(base, "easyocr_crash.log")
|
||||
|
||||
CRASH_LOG = _get_crash_log_path()
|
||||
@@ -81,10 +75,12 @@ except Exception as e:
|
||||
|
||||
|
||||
def _init_reader():
|
||||
"""初始化 EasyOCR reader(GPU 优先)。"""
|
||||
"""初始化 EasyOCR reader(GPU 优先,父进程可强制 CPU)。"""
|
||||
try:
|
||||
import torch
|
||||
use_gpu = torch.cuda.is_available()
|
||||
# 父进程 EASYOCR_FORCE_CPU=1 → 强制 CPU(显存反复 OOM 时降级,防冻结)
|
||||
_force_cpu = os.environ.get("EASYOCR_FORCE_CPU") == "1"
|
||||
use_gpu = (not _force_cpu) and torch.cuda.is_available()
|
||||
except Exception:
|
||||
use_gpu = False
|
||||
|
||||
@@ -152,6 +148,12 @@ def _main():
|
||||
sys.stdout.write(out + "\n")
|
||||
sys.stdout.flush()
|
||||
except Exception as e:
|
||||
estr = str(e)
|
||||
# ⭐ CUDA OOM / kernel error:GPU context 已损坏,继续跑只会反复卡死占显存
|
||||
# → 立即退出进程释放显存,父进程检测到 stdout 关闭后自动重启/降级 CPU
|
||||
if "cuda" in estr.lower() or "out of memory" in estr.lower():
|
||||
_write_crash_log(f"{datetime.now()} [easyocr_worker] CUDA 错误,主动退出释放显存: {estr[:200]}")
|
||||
_flush_exit(f"CUDA 错误,主动退出释放显存: {estr[:200]}")
|
||||
out = json.dumps({"ok": False, "error": str(e)}, ensure_ascii=False)
|
||||
sys.stdout.write(out + "\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
Reference in New Issue
Block a user