【问题标题】:pywin32 function in pygame causing program to hang / "python.exe is not responding"pygame中的pywin32函数导致程序挂起/“python.exe没有响应”
【发布时间】:2015-01-11 07:09:04
【问题描述】:

我有一个程序,它使用 pywin32 获取游戏的屏幕截图并使用 pygame 显示它。我遇到间歇性崩溃/挂起,程序会给出通常的窗口“不响应”错误,说 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())在程序挂起/无响应时仍会执行。

整个程序的要点:https://gist.github.com/Andygmb/f8ae761e689788136fc0

【问题讨论】:

    标签: python winapi pywin32 win32gui


    【解决方案1】:

    我们之前谈过 IRC。

    我认为您的问题与使用windll.user32.PrintWindow有关。看着Microsoft documentation for this function,这行引起了我的注意:

    "注意这是一个阻塞或同步函数,可能不会返回 立即地。此函数返回的速度取决于运行时 网络状态、打印服务器配置等因素 打印机驱动程序实施——难以预测的因素 在编写应用程序时。从一个线程调用这个函数 管理与用户界面的交互可以使应用程序 似乎没有反应。”

    所以这可能是相关的。

    在 while running 循环的底部添加 time.sleep(1)(在导入时间之后)似乎可以防止我的系统崩溃,所以如果这对你有用并且一秒钟的延迟是可以接受的,这是一个选项.

    您真正想要做的是能够在后台调用 PrintWindow 并在 PrintWindow 返回时更新屏幕,但您可能不得不在文件读/写锁和/或线程方面做一些愚蠢的事情。所以这真的取决于这是为了什么以及什么对你来说更重要。

    【讨论】:

    • 看起来这就是问题所在 - 我已将 Printwindow 函数放入主循环之外的单独线程中,这(似乎)已经停止了所有崩溃问题。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多