CreateCompatibleDC() 或 DeleteDC() 在 Python 中继续循环失败 - 可能是内存泄漏?
CreateCompatibleDC() or DeleteDC() fail in continues loop in Python - possible memory leak?
我正在使用下面这个特定的 window 屏幕捕获例程在循环中提供 opencv window。
问题:循环中的数百个循环后,它突然在代码中下面标记的两个失败点之一失败。
我怀疑可能存在内存泄漏,但如果我没记错的话,我会删除并释放需要的内容以及我(重新)select 对象在我删除之前 它。
(我使用这种方法的原因,因为它对我来说很重要能够捕获特定的window,即使它处于非活动状态并且在后台 而且我没有发现任何其他 module/method 确实有效。)
我忽略了什么?
import win32gui
import win32ui
from PIL import Image
import numpy as np
import cv2
while True:
target_window = win32gui.FindWindow(None, ("Analytics dashboard - Google Chrome"))
hwndDC = win32gui.GetWindowDC(target_window)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC() #### <-- RANDOM FAIL POINT 1: win32ui.error: CreateCompatibleDC failed
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
result = windll.user32.PrintWindow(target_window, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
mfcDC.DeleteDC() #### <-- RANDOM FAIL POINT 2: win32ui.error: DeleteDC failed
saveDC.DeleteDC()
win32gui.DeleteObject(saveBitMap.GetHandle())
win32gui.ReleaseDC(target_window, hwndDC)
image = cv2.cvtColor(np.array(screen_image), cv2.IMREAD_ANYCOLOR)
我用 ctypes.windll.user32.PrintWindow
尝试了上面的代码并且没有 GDI 泄漏。 PrintWindow
的第三个参数应该是 PW_CLIENTONLY
(1),或者有未记录的 PW_RENDERFULLCONTENT
(2) 选项。未记录的代码是不可靠的。不知道常量(3)指的是什么
如果 Chrome 是最上面的 window 你应该只截取桌面的屏幕截图。这将是合规的。
如果你去掉循环外的一些代码可能会有所帮助,至少会更有效率。
import ctypes
import win32gui
import win32ui
import win32con
from PIL import Image
hdesktop = win32gui.GetDesktopWindow()
(l, r, width, height) = win32gui.GetClientRect(hdesktop)
hdc = win32gui.GetWindowDC(hdesktop)
dc = win32ui.CreateDCFromHandle(hdc)
memdc = dc.CreateCompatibleDC()
bitmap = win32ui.CreateBitmap()
bitmap.CreateCompatibleBitmap(dc, width, height)
memdc.SelectObject(bitmap)
while True:
hwnd = win32gui.FindWindow("Chrome_WidgetWin_1", None)
if hwnd == 0:
break
result = ctypes.windll.user32.PrintWindow(hwnd, memdc.GetSafeHdc(), 2)
if result == 1:
bytes = bitmap.GetBitmapBits(True)
img = Image.frombuffer('RGB', (width, height), bytes, 'raw', 'BGRX', 0, 1)
img.save("file.bmp")
#break
dc.DeleteDC()
memdc.DeleteDC()
win32gui.DeleteObject(bitmap.GetHandle())
win32gui.ReleaseDC(hwnd, hdc)
您还可以在顶部添加 ctypes.windll.shcore.SetProcessDpiAwareness(2)
我正在使用下面这个特定的 window 屏幕捕获例程在循环中提供 opencv window。
问题:循环中的数百个循环后,它突然在代码中下面标记的两个失败点之一失败。
我怀疑可能存在内存泄漏,但如果我没记错的话,我会删除并释放需要的内容以及我(重新)select 对象在我删除之前 它。
(我使用这种方法的原因,因为它对我来说很重要能够捕获特定的window,即使它处于非活动状态并且在后台 而且我没有发现任何其他 module/method 确实有效。)
我忽略了什么?
import win32gui
import win32ui
from PIL import Image
import numpy as np
import cv2
while True:
target_window = win32gui.FindWindow(None, ("Analytics dashboard - Google Chrome"))
hwndDC = win32gui.GetWindowDC(target_window)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC() #### <-- RANDOM FAIL POINT 1: win32ui.error: CreateCompatibleDC failed
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
result = windll.user32.PrintWindow(target_window, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
mfcDC.DeleteDC() #### <-- RANDOM FAIL POINT 2: win32ui.error: DeleteDC failed
saveDC.DeleteDC()
win32gui.DeleteObject(saveBitMap.GetHandle())
win32gui.ReleaseDC(target_window, hwndDC)
image = cv2.cvtColor(np.array(screen_image), cv2.IMREAD_ANYCOLOR)
我用 ctypes.windll.user32.PrintWindow
尝试了上面的代码并且没有 GDI 泄漏。 PrintWindow
的第三个参数应该是 PW_CLIENTONLY
(1),或者有未记录的 PW_RENDERFULLCONTENT
(2) 选项。未记录的代码是不可靠的。不知道常量(3)指的是什么
如果 Chrome 是最上面的 window 你应该只截取桌面的屏幕截图。这将是合规的。
如果你去掉循环外的一些代码可能会有所帮助,至少会更有效率。
import ctypes
import win32gui
import win32ui
import win32con
from PIL import Image
hdesktop = win32gui.GetDesktopWindow()
(l, r, width, height) = win32gui.GetClientRect(hdesktop)
hdc = win32gui.GetWindowDC(hdesktop)
dc = win32ui.CreateDCFromHandle(hdc)
memdc = dc.CreateCompatibleDC()
bitmap = win32ui.CreateBitmap()
bitmap.CreateCompatibleBitmap(dc, width, height)
memdc.SelectObject(bitmap)
while True:
hwnd = win32gui.FindWindow("Chrome_WidgetWin_1", None)
if hwnd == 0:
break
result = ctypes.windll.user32.PrintWindow(hwnd, memdc.GetSafeHdc(), 2)
if result == 1:
bytes = bitmap.GetBitmapBits(True)
img = Image.frombuffer('RGB', (width, height), bytes, 'raw', 'BGRX', 0, 1)
img.save("file.bmp")
#break
dc.DeleteDC()
memdc.DeleteDC()
win32gui.DeleteObject(bitmap.GetHandle())
win32gui.ReleaseDC(hwnd, hdc)
您还可以在顶部添加 ctypes.windll.shcore.SetProcessDpiAwareness(2)