Python脚本(PyAutoGUI+OpenCV)内存占用过高问题求助
内存泄漏优化方案与自动重启方法
核心问题分析
你的脚本内存暴涨的主要原因是无限递归调用:find_and_click_text 和 skip 互相调用,且未找到目标时递归自身,导致调用栈持续累积,内存无法释放。此外,每次函数执行都重复读取模板图片,也会增加不必要的内存开销。
优化方案(彻底解决内存泄漏)
1. 替换递归为循环
递归不适合这种持续运行的场景,改用 while 循环可避免调用栈无限增长,从根源解决内存堆积问题。
2. 预加载模板图片
将模板图片在脚本启动时加载一次,而非每次函数调用都从磁盘读取,减少IO开销和内存碎片。
3. 修复按键释放问题
原代码中使用 keyDown 但未调用 keyUp,会导致按键一直处于按下状态,需补充释放操作。
4. 显式触发垃圾回收
在循环中定期触发垃圾回收,帮助清理不再使用的对象。
优化后的代码
import pyautogui import cv2 import numpy as np import time import gc # 预加载模板图片,仅初始化一次 TEMPLATE_TEXT = cv2.imread("C:/Users/Owner/template2.png", cv2.IMREAD_COLOR) TEMPLATE_SKIP = cv2.imread("C:/Users/Owner/skip2.png", cv2.IMREAD_COLOR) H_TEXT, W_TEXT = TEMPLATE_TEXT.shape[:-1] H_SKIP, W_SKIP = TEMPLATE_SKIP.shape[:-1] def take_screenshot(): screenshot = pyautogui.screenshot() screenshot = np.array(screenshot) return cv2.cvtColor(screenshot, cv2.COLOR_RGB2BGR) def find_and_click_text(): num = 0 while True: screenshot = take_screenshot() result = cv2.matchTemplate(screenshot, TEMPLATE_TEXT, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(result) if max_val > 0.8: # 定位并点击目标 center_x = max_loc[0] + W_TEXT / 2 center_y = max_loc[1] + H_TEXT / 2 pyautogui.moveTo((center_x, center_y)) pyautogui.click() # 释放之前按下的按键 pyautogui.keyUp('fn') pyautogui.keyUp('f12') # 切换到跳过逻辑 skip() break else: num += 1 if num >= 10: skip() break time.sleep(0.1) # 减少CPU占用 gc.collect() # 触发垃圾回收 def skip(): num = 0 while True: screenshot = take_screenshot() result = cv2.matchTemplate(screenshot, TEMPLATE_SKIP, cv2.TM_CCOEFF_NORMED) _, max_val2, _, max_loc2 = cv2.minMaxLoc(result) if max_val2 > 0.8: center_x = max_loc2[0] + W_SKIP / 2 center_y = max_loc2[1] + H_SKIP / 2 pyautogui.moveTo((center_x, center_y)) pyautogui.click() pyautogui.keyUp('fn') pyautogui.keyUp('f8') time.sleep(0.5) find_and_click_text() break else: num += 1 if num >= 10: find_and_click_text() break time.sleep(0.1) gc.collect() if __name__ == "__main__": find_and_click_text()
自动重启方案(作为 fallback)
若优化后仍存在内存问题,可使用以下两种方式实现自动重启:
方法1:基于内存阈值重启
使用 psutil 库监控内存占用,超过设定阈值时自动重启脚本:
import os import psutil import subprocess import time # 配置参数 MAIN_SCRIPT = "your_main_script.py" # 替换为你的主脚本文件名 MEMORY_THRESHOLD_GB = 2 # 内存超过2GB时重启 def restart_script(): # 终止现有进程 for proc in psutil.process_iter(['pid', 'cmdline']): try: if MAIN_SCRIPT in ' '.join(proc.info['cmdline']): proc.kill() except (psutil.NoSuchProcess, psutil.AccessDenied): pass # 启动新进程 subprocess.Popen(["python", MAIN_SCRIPT]) if __name__ == "__main__": restart_script() # 首次启动主脚本 while True: for proc in psutil.process_iter(['pid', 'cmdline']): try: if MAIN_SCRIPT in ' '.join(proc.info['cmdline']): mem_usage = proc.memory_info().rss / (1024**3) # 转换为GB if mem_usage > MEMORY_THRESHOLD_GB: restart_script() break except (psutil.NoSuchProcess, psutil.AccessDenied): pass time.sleep(10) # 每10秒检查一次
安装依赖:pip install psutil
方法2:定时重启
固定时间间隔重启脚本,适用于内存增长规律的场景:
import subprocess import time MAIN_SCRIPT = "your_main_script.py" RESTART_INTERVAL = 300 # 5分钟重启一次(单位:秒) while True: proc = subprocess.Popen(["python", MAIN_SCRIPT]) time.sleep(RESTART_INTERVAL) proc.kill()
内容的提问来源于stack exchange,提问作者penguinpowerss
相关产品推荐
相关产品推荐

