mhammond / pywin32

Python for Windows (pywin32) Extensions
5.06k stars 799 forks source link

When using screencapture with win32gui, memory leak occurs #2171

Open muhaha211 opened 9 months ago

muhaha211 commented 9 months ago
import numpy as np
import win32gui, win32ui, win32con
import time 
import cv2
import psutil

def memory_usage(message: str = 'debug'):
    # current process RAM usage
    p = psutil.Process()
    rss = p.memory_info().rss / 2 ** 20 # Bytes to MB
    print(f"[{message}] memory usage: {rss: 10.5f} MB")

class ImageSearch:

    # constructor
    def __init__(self, windowx=0, windowy=0, windowr=0):
        self.hwnd = win32gui.GetDesktopWindow()  # Get the desktop window handle

    def screencapture(self):
        # Get the window size
        window_rect = win32gui.GetWindowRect(self.hwnd)
        self.left = window_rect[0]
        self.top = window_rect[1]
        self.weight = window_rect[2] - window_rect[0]
        self.height = window_rect[3] - window_rect[1]

        # Get the window image data
        wDC = win32gui.GetWindowDC(self.hwnd)
        dcObj = win32ui.CreateDCFromHandle(wDC)
        cDC = dcObj.CreateCompatibleDC()
        dataBitMap = win32ui.CreateBitmap()
        dataBitMap.CreateCompatibleBitmap(dcObj, self.weight, self.height)
        cDC.SelectObject(dataBitMap)
        cDC.BitBlt((0, 0), (self.weight, self.height), dcObj, (self.left, self.top), win32con.SRCCOPY)

        # Convert the raw data into a format OpenCV can read
        signedIntsArray = dataBitMap.GetBitmapBits(True)
        img = np.frombuffer(signedIntsArray, dtype='uint8')
        img.shape = (self.height, self.weight, 4)

        # Clean up resources
        dcObj.DeleteDC()
        cDC.DeleteDC()
        win32gui.ReleaseDC(self.hwnd, wDC)
        win32gui.DeleteObject(dataBitMap.GetHandle())

        img = img[..., :3]
        img = np.ascontiguousarray(img)

        return img

a = ImageSearch()
while True:
    memory_usage('#1')
    abc = a.screencapture()

Python 3.10.11, pywin306 on windows10. The code causes memory to keep increasing over time when executed. It appears that something in the win32 capture method is causing a leak, but I'm not sure of the exact cause or solution. Despite searching online, there doesn't seem to be an obvious issue with the code. Is there a solution available?

mhammond commented 9 months ago

You'd need to narrow you code down even further and work out which pywin32 function is actually causing the leak. Once identified a fix should be fairly easy but will require a new build of pywin32.

Avasam commented 3 weeks ago

If I can replicate, I might wanna take a look into it. I use very similar code in https://github.com/Toufool/AutoSplit/blob/master/src/capture_method/BitBltCaptureMethod.py