pygame 中的 pywin32 函数导致程序挂起/"python.exe is not responding"
pywin32 function in pygame causing program to hang / "python.exe is not responding"
我有一个程序使用 pywin32 截取游戏的屏幕截图并使用 pygame 显示它。我遇到间歇性 crashing/hanging 程序会给出通常的 windows "not responding" 错误,说 python.exe 在程序大约 5-10 秒后没有响应 运行 有时候。
我已将其缩小为以下功能:
def screengrab(self):
hwnd = self.aoe_hwnd
left, top, right, bot = win32gui.GetClientRect(hwnd)
w = right - left
h = bot - top
#returns the device context (DC) for the entire window, including title bar, menus, and scroll bars.
hwndDC = win32gui.GetWindowDC(hwnd)
#Creates a DC object from an integer handle.
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
#Creates a memory device context (DC) compatible with the specified device.
saveDC = mfcDC.CreateCompatibleDC()
saveDC.SetWindowOrg((w - self.map_w,h - self.map_h))
#Creates bitmap Object
saveBitMap = win32ui.CreateBitmap()
#Creates a bitmap object from a HBITMAP.
saveBitMap.CreateCompatibleBitmap(mfcDC, self.map_w, self.map_h)
saveDC.SelectObject(saveBitMap)
# Change the line below depending on whether you want the whole window
# or just the client area.
#result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer(
'RGB',
(bmpinfo['bmWidth'], bmpinfo['bmHeight']),
bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)
if result == 1:
tmp = cStringIO.StringIO()
im = im.resize(self.window_size)
im.save(tmp, "bmp")
tmp.seek(0)
return tmp
我是 win32 api 的新手,我真的不完全确定是什么导致它那样挂起。奇怪的是,放置在程序主循环中的打印语句(也调用了 screengrab()),在程序 hung/not 响应时仍会执行。
要点上的整个程序:https://gist.github.com/Andygmb/f8ae761e689788136fc0
我们早些时候在 IRC 上讨论过。
我认为您的问题与 windll 的使用有关。user32.PrintWindow。查看 Microsoft documentation for this function,这一行引起了我的注意:
"Note This is a blocking or synchronous function and might not return
immediately. How quickly this function returns depends on run-time
factors such as network status, print server configuration, and
printer driver implementation—factors that are difficult to predict
when writing an application. Calling this function from a thread that
manages interaction with the user interface could make the application
appear to be unresponsive."
所以这可能是相关的。
在 while 运行 循环的底部添加 time.sleep(1)(在导入时间之后)似乎可以防止我的系统崩溃,所以如果这对你和一个人有效第二次延迟是可以接受的,这是一种选择。
您真正想要做的是能够在后台调用 PrintWindow 并在 PrintWindow returns 时更新屏幕,但您可能不得不用文件 read/write 锁 and/or穿线。所以这真的取决于这是为了什么以及什么对你更重要。
我有一个程序使用 pywin32 截取游戏的屏幕截图并使用 pygame 显示它。我遇到间歇性 crashing/hanging 程序会给出通常的 windows "not responding" 错误,说 python.exe 在程序大约 5-10 秒后没有响应 运行 有时候。
我已将其缩小为以下功能:
def screengrab(self):
hwnd = self.aoe_hwnd
left, top, right, bot = win32gui.GetClientRect(hwnd)
w = right - left
h = bot - top
#returns the device context (DC) for the entire window, including title bar, menus, and scroll bars.
hwndDC = win32gui.GetWindowDC(hwnd)
#Creates a DC object from an integer handle.
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
#Creates a memory device context (DC) compatible with the specified device.
saveDC = mfcDC.CreateCompatibleDC()
saveDC.SetWindowOrg((w - self.map_w,h - self.map_h))
#Creates bitmap Object
saveBitMap = win32ui.CreateBitmap()
#Creates a bitmap object from a HBITMAP.
saveBitMap.CreateCompatibleBitmap(mfcDC, self.map_w, self.map_h)
saveDC.SelectObject(saveBitMap)
# Change the line below depending on whether you want the whole window
# or just the client area.
#result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer(
'RGB',
(bmpinfo['bmWidth'], bmpinfo['bmHeight']),
bmpstr, 'raw', 'BGRX', 0, 1)
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)
if result == 1:
tmp = cStringIO.StringIO()
im = im.resize(self.window_size)
im.save(tmp, "bmp")
tmp.seek(0)
return tmp
我是 win32 api 的新手,我真的不完全确定是什么导致它那样挂起。奇怪的是,放置在程序主循环中的打印语句(也调用了 screengrab()),在程序 hung/not 响应时仍会执行。
要点上的整个程序:https://gist.github.com/Andygmb/f8ae761e689788136fc0
我们早些时候在 IRC 上讨论过。
我认为您的问题与 windll 的使用有关。user32.PrintWindow。查看 Microsoft documentation for this function,这一行引起了我的注意:
"Note This is a blocking or synchronous function and might not return immediately. How quickly this function returns depends on run-time factors such as network status, print server configuration, and printer driver implementation—factors that are difficult to predict when writing an application. Calling this function from a thread that manages interaction with the user interface could make the application appear to be unresponsive."
所以这可能是相关的。
在 while 运行 循环的底部添加 time.sleep(1)(在导入时间之后)似乎可以防止我的系统崩溃,所以如果这对你和一个人有效第二次延迟是可以接受的,这是一种选择。
您真正想要做的是能够在后台调用 PrintWindow 并在 PrintWindow returns 时更新屏幕,但您可能不得不用文件 read/write 锁 and/or穿线。所以这真的取决于这是为了什么以及什么对你更重要。