【问题标题】:detecting idle time using python使用python检测空闲时间
【发布时间】:2010-10-29 01:14:33
【问题描述】:

如何使用 Python 在 Windows 上检测系统是否空闲(即没有键盘或鼠标活动)。 before 已经问过这个问题,但 pywin32 模块中似乎没有 GetLastInputInfo。

【问题讨论】:

  • 既然问了,为什么又问了?您认为哪些变化会产生不同的答案?
  • 也许现在有人可以回答它,但老问题被埋没在年龄和默默无闻中。你怎么能“撞”别人的老问题?
  • 当它之前被问到时,答案是关于检测鼠标点击,这与该问题的答案相去甚远!

标签: python winapi


【解决方案1】:

其实你可以通过cytpes库访问GetLastInputInfo:

import ctypes
GetLastInputInfo = ctypes.windll.User32.GetLastInputInfo  # callable function pointer

这可能不是你想要的,因为它不提供整个系统的空闲信息,而只是关于调用该函数的会话。 See MSDN docs.

或者,您也可以check if the system is locked,或者如果屏幕保护程序已启动。

【讨论】:

    【解决方案2】:
    from ctypes import Structure, windll, c_uint, sizeof, byref
    
    class LASTINPUTINFO(Structure):
        _fields_ = [
            ('cbSize', c_uint),
            ('dwTime', c_uint),
        ]
    
    def get_idle_duration():
        lastInputInfo = LASTINPUTINFO()
        lastInputInfo.cbSize = sizeof(lastInputInfo)
        windll.user32.GetLastInputInfo(byref(lastInputInfo))
        millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
        return millis / 1000.0
    

    致电get_idle_duration() 以获取空闲时间(以秒为单位)。

    【讨论】:

    • 另一个库可能以不兼容的方式在windll.user32.GetLastInputInfo 上设置argtypes、restype 或errcheck,因此您应该使用自己的WinDLL 实例,例如user32 = WinDLL('user32', use_last_error=True).
    【解决方案3】:

    好像GetLastInputInfo 现在在 pywin32 中可用:

    win32api.GetLastInputInfo()
    

    执行此操作并从最后一个用户输入操作返回计时器滴答声。

    这里有一个示例程序

    import time
    import win32api
    for i in range(10):
       print(win32api.GetLastInputInfo())
       time.sleep(1)
    

    如果在脚本休眠时按下一个键/移动鼠标,打印的数字会改变。

    【讨论】:

      【解决方案4】:

      @FogleBird 的回答非常酷且有效,但我急忙不确定它是如何工作的,所以这里有一个小测试示例。一个线程正在启​​动,每 10 秒查找最后一次空闲时间。如果在这个时间窗口内有任何动作,就会被打印出来。

      from ctypes import Structure, windll, c_uint, sizeof, byref
      import threading
      
      //Print out every n seconds the idle time, when moving mouse, this should be < 10
      def printit():
        threading.Timer(10.0, printit).start()
        print get_idle_duration()
      
      
      
      class LASTINPUTINFO(Structure):
          _fields_ = [
              ('cbSize', c_uint),
              ('dwTime', c_uint),
          ]
      
      def get_idle_duration():
          lastInputInfo = LASTINPUTINFO()
          lastInputInfo.cbSize = sizeof(lastInputInfo)
          windll.user32.GetLastInputInfo(byref(lastInputInfo))
          millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
          return millis / 1000.0
      
      printit()
      

      【讨论】:

        【解决方案5】:
        import win32api
        def getIdleTime():
            return (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
        

        【讨论】:

        • 这会产生一个小于 1 的数字,该数字似乎不会随着时间的推移而增加。当检测到输入时它会重置为零,但随后它会变成 0.015 或 0.016 并保持在那里。
        【解决方案6】:

        到目前为止,基本上有两种类型的答案。一种使用pywin32(通过win32api,另一种使用ctypes。我能想到的唯一区别它们就是执行时间,所以这里是timeit测试的结果:

        # idlefuncs.py
        
        import ctypes
        from ctypes import Structure, c_uint, sizeof, byref
        
        import win32api
        
        user32 = ctypes.WinDLL("user32", use_last_error=True)
        kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
        
        class LASTINPUTINFO(Structure):
            _fields_ = [
                ('cbSize', c_uint),
                ('dwTime', c_uint),
            ]
        
        
        def get_idle_duration():
            lastInputInfo = LASTINPUTINFO()
            lastInputInfo.cbSize = sizeof(lastInputInfo)
            user32.GetLastInputInfo(byref(lastInputInfo))
            millis = kernel32.GetTickCount() - lastInputInfo.dwTime
            return millis / 1000.0
        
        
        def getIdleTime():
            return (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
        
        

        在 ipython 中:

        In[1]: from idlefuncs import *
        
        In[2]: %timeit get_idle_duration()
        1.21 µs ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
        In[4]: %timeit getIdleTime()
        465 ns ± 7.69 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
        
        

        与我的预期相反,ctypes 版本的耗时是原来的 2.6 倍!

        【讨论】:

          猜你喜欢
          • 2012-09-20
          • 2013-03-28
          • 2010-11-13
          • 1970-01-01
          • 2010-10-14
          • 2021-08-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多