Open ColdLighting opened 1 year ago
+1; this issue also happens for me after my program runs for ~3 hours.
From log:
> INFO 2023/09/13 22:06:27 [mouse_monitor.py:120] origin window rect:(0, 0, 0, 0)
Source mss:
class MSS(MSSBase):
def __init__(self, /, **kwargs: Any) -> None:
...
self._handles.region_width_height = (0, 0)
if self._handles.region_width_height != (width, height):
...
self._handles.data = ctypes.create_string_buffer(width * height * 4) # [2]
May be: if first cordinate (width, height) == (0, 0); self._handles.data - not set and Error.
Need: ?
def __init__(self, /, **kwargs: Any) -> None:
...
self._handles.region_width_height = (None, None)
Before changing the current code, we will need a regression test so that we can validate both the issue and the fix.
mss.exception.ScreenShotError: gdi32.GetDIBits() failed.
I get the same error after using 'mss' with 'threading.Timer' for a while. My code uses mss to get one pixel from the screen at the same place in a loop.
@Tratux can you share a minimal reproduction code please?
@BoboTiG I've tested and I got the same error with this code. The code executed for at least 10 min without an error.
import mss
import threading
import numpy as np
def loopFunc():
pix = getPixel(100, 100)
print(pix)
timer = threading.Timer(0.1, loopFunc)
timer.start()
def getPixel(x, y):
region = (x, y, x+1, y+1)
pixel = np.asarray(mss.mss().grab(region))
return pixel
if __name__ == "__main__":
loopFunc()
@Tratux This bad code: Intro Thread, create new Thread and new ...
If run in Python 3.12 After 2 cycle
Exception in thread Thread-1:
...
File "C:\Program Files\Python312\Lib\threading.py", line 971, in start
_start_new_thread(self._bootstrap, ())
RuntimeError: can't create new thread at interpreter shutdown
If run in 3.11 After some time:
Exception in thread Thread-4998:
Traceback (most recent call last):
File "D:\Program Files\Python\Lib\threading.py", line 1038, in _bootstrap_inner
self.run()
File "D:\Program Files\Python\Lib\threading.py", line 1394, in run
self.function(*self.args, **self.kwargs)
File "D:\Program Files\Python\t.py", line 6, in loopFunc
pix = getPixel(100, 100)
^^^^^^^^^^^^^^^^^^
File "D:\Program Files\Python\t.py", line 14, in getPixel
pixel = np.asarray(mss.mss().grab(region))
^^^^^^^^^^^^^^^^^^^^^^
File "D:\Program Files\Python\Lib\site-packages\mss\base.py", line 90, in grab
screenshot = self._grab_impl(monitor)
^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\Program Files\Python\Lib\site-packages\mss\windows.py", line 252, in _grab_impl
raise ScreenShotError("gdi32.GetDIBits() failed.")
mss.exception.ScreenShotError: gdi32.GetDIBits() failed.
For fast: threading.Timer(0.001, loopFunc) Too: Exception in thread Thread-4998:
Im run Process Explorer: and saw after GDI handles ~ 10K python.exe crash.
This Windows limit GDI handles. https://learn.microsoft.com/uk-ua/windows/win32/sysinfo/user-objects?redirectedfrom=MSDN HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota My Win11 limit - 10K
Also in my Windows Event Viewer: Windows Logs->Application Windows Error Reporting : Event: GDIObjectLeak python.exe https://stackoverflow.com/questions/8302287/how-to-debug-gdi-object-leaks
The Tratux error is not the same as the original error.
For first issue : If run a test from #270 for the current version
import mss
with mss.mss() as sct:
region0 = {"top": 0, "left": 0, "width": 0, "height": 0}
sct.grab(region0)
Same error:
File "D:\Program Files\Python\Lib\site-packages\mss\windows.py", line 250, in _grab_impl
bits = gdi.GetDIBits(memdc, self._handles.bmp, 0, height, self._handles.data, self._handles.bmi, DIB_RGB_COLORS)
^^^^^^^^^^^^^^^^^^
AttributeError: '_thread._local' object has no attribute 'data'
I'm seeing the same error message here, mss.exception.ScreenShotError: gdi32.GetDiBits() failed. It was working fine for a few hours and then stopped. Here is the relevant code.
def __init__(self):
self.observation_space = gymnasium.spaces.Box(low=0, high=255, shape=(1, 83, 100), dtype=np.uint8)
self.action_space = gymnasium.spaces.Discrete(3)
self.cap = mss
self.game_location = {'top': 300, 'left': 0, 'width': 600, 'height': 500}
self.done_location = {'top': 405, 'left': 340, 'width': 660, 'height': 70}
def get_observation(self):
raw = np.array(self.cap.grab(self.game_location))[:, :, :3] #Error occurs here!
gray = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)
resized = cv2.resize(gray, (100, 83))
channel = np.reshape(resized, (1, 83, 100))
return channel
General information:
Description of the warning/error
I packaged my project as an exe using pyinstaller and ran it. At some point on the 6th day, I reported a ScreenShotError error when taking a screenshot, and an AttributeError error occurred in subsequent screenshots.
Full message
Other details
First of all, thank you very much for providing a high-performance screenshot tool, I like it very much!
The following is a detailed description and part of the code for the problem I encountered.
I used pynput.mouse to monitor the mouse. When the mouse is left-clicked on the specified area in the program window I specified, I will take a screenshot and save some other additional coordinate information. Then I used pyinstaller to package my project as an exe and run it, but after about 6 days of running it threw a ScreenShotError at some point, and all subsequent clicks would throw an exception AttributeError: _data, and subsequently I obtained the system zoom and foreground window coordinates. , the xy value passed by pynput will become 0 !
I checked the relevant issues and seemed to not find a solution to the problem related to me. Then I tried to read your source code and found that the location where the exception was thrown was in mss/windows. py:252:
it judged bits != height. I checked my logs. When the last error was reported, the monitor parameter I passed was correct: (3, 22, 794, 629)
so it can only be the value of bits has a problem. But sorry, I don't know much about win32api, so I went to Microsoft's official website to check the relevant documents and roughly understood the role of BitBlt/GetDIBits/GetWindowDC. I guess the root cause may be that an invalid handle was obtained when windows.py:112 was initialized causing this error:
I briefly checked the code of pynput.mouse and learned that it is a single-thread processing callback function, which means that the first time this error occurred in its internal sub-thread, it affected all my subsequent code that calls win32api, just like this:
Of course, the above It's just my speculation based on the documentation and source code. I hope you can reply. Thank you again!
How I get Win10 Scaling
mouse_monitor.py simplified example
How I get foreground window rect
Upvote & Fund