Python 在模块级运行与在函数范围内运行时,是什么导致此代码产生不同的结果?
我试图通过Windows API枚举可用的显示监视器。然而,我有一些奇怪的行为,我无法理解。也就是说,函数正确运行,但仅当它不在函数内部时 如果我将其放置在模块级别,如下所示: 模块代码 一切正常。它为我连接的两台显示器打印Python 在模块级运行与在函数范围内运行时,是什么导致此代码产生不同的结果?,python,windows,winapi,ctypes,user32,Python,Windows,Winapi,Ctypes,User32,我试图通过Windows API枚举可用的显示监视器。然而,我有一些奇怪的行为,我无法理解。也就是说,函数正确运行,但仅当它不在函数内部时 如果我将其放置在模块级别,如下所示: 模块代码 一切正常。它为我连接的两台显示器打印句柄和矩形 输出: 所以,完全相同的代码,除了现在在函数内部 输出 调用结果:65537无0 0 它没有吐出所有连接的监视器和一个成功代码,而是只吐出一个监视器和一个0,这意味着函数失败 有人知道这是什么原因吗?我被难住了 使用函数时,enum\u回调在enum\u mon
句柄
和矩形
输出:
所以,完全相同的代码,除了现在在函数内部
输出
调用结果:65537无0
0
它没有吐出所有连接的监视器和一个成功代码,而是只吐出一个监视器和一个0,这意味着函数失败
有人知道这是什么原因吗?我被难住了 使用函数时,
enum\u回调
在enum\u mons
的Python帧被垃圾收集时被释放。因此,当Windows试图为每个监视器调用它时,它是否仍然存在是一场竞赛。全局定义回调——或者使用类
您的回调也应该返回True以继续枚举
import ctypes
from ctypes import wintypes
LPRECT = ctypes.POINTER(wintypes.RECT)
# Callback Factory
MonitorEnumProc = ctypes.WINFUNCTYPE(
ctypes.c_bool,
wintypes.HMONITOR,
wintypes.HDC,
LPRECT,
wintypes.LPARAM)
ctypes.windll.user32.EnumDisplayMonitors.restype = wintypes.BOOL
ctypes.windll.user32.EnumDisplayMonitors.argtypes = [
wintypes.HDC,
LPRECT,
MonitorEnumProc,
wintypes.LPARAM]
def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData
print lprcMonitor[0].right, lprcMonitor[0].bottom
return True # continue enumeration
# Make the callback function
enum_callback = MonitorEnumProc(_monitorEnumProc)
def enum_mons():
'''Enumerate the display monitors.'''
return ctypes.windll.user32.EnumDisplayMonitors(
None,
None,
enum_callback,
0)
if __name__ == '__main__':
print 'return code: %d' % enum_mons()
这不是完全相同的代码。其中一个有一个
打印
,另一个没有,还有一个奇怪的列表摆在那里,什么都不做。@user2357112whoop!我以为我把那些都拿走了。现在修好了。代码相同。请再次运行这两个版本,以确保获得发布的输出。如果与您发布的输出(包括格式)有任何不同,请更新问题。当您这样做时,许多bug会神秘地消失。@user2357112更新了问题代码。以同样的结果在我这边运行。代码是复制/粘贴的,其中一个是函数。文本“返回代码:”
不会出现在您显示的任何输出中。真奇怪。
>>> call result: 65537 None <__main__.LP_RECT object at 0x02250EE0> 0
>>> call result: 65539 None <__main__.LP_RECT object at 0x02250EE0> 0
[Finished in 0.1s]
def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData
def enum_mons():
# Callback Factory
MonitorEnumProc = WINFUNCTYPE(
ctypes.c_bool,
ctypes.wintypes.HMONITOR,
ctypes.wintypes.HDC,
ctypes.POINTER(RECT),
ctypes.wintypes.LPARAM
)
# Make the callback function
enum_callback = MonitorEnumProc(_monitorEnumProc)
# Enumerate the windows
print 'return code: %d' % windll.user32.EnumDisplayMonitors(
None,
None,
enum_callback,
0
)
if __name__ == '__main__':
enum_mons()
call result: 65537 None <__main__.LP_RECT object at 0x02250E90> 0
0
import ctypes
from ctypes import wintypes
LPRECT = ctypes.POINTER(wintypes.RECT)
# Callback Factory
MonitorEnumProc = ctypes.WINFUNCTYPE(
ctypes.c_bool,
wintypes.HMONITOR,
wintypes.HDC,
LPRECT,
wintypes.LPARAM)
ctypes.windll.user32.EnumDisplayMonitors.restype = wintypes.BOOL
ctypes.windll.user32.EnumDisplayMonitors.argtypes = [
wintypes.HDC,
LPRECT,
MonitorEnumProc,
wintypes.LPARAM]
def _monitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData):
print 'call result:', hMonitor, hdcMonitor, lprcMonitor, dwData
print lprcMonitor[0].right, lprcMonitor[0].bottom
return True # continue enumeration
# Make the callback function
enum_callback = MonitorEnumProc(_monitorEnumProc)
def enum_mons():
'''Enumerate the display monitors.'''
return ctypes.windll.user32.EnumDisplayMonitors(
None,
None,
enum_callback,
0)
if __name__ == '__main__':
print 'return code: %d' % enum_mons()