如何在Mac / Python中检查屏幕是否已关闭?

时间:2013-01-10 07:12:24

标签: python macos

如何根据Mac / Python下“系统偏好设置”中的“节能设置”检查屏幕是否已关闭?

2 个答案:

答案 0 :(得分:5)

快速而肮脏的解决方案:致电ioreg并解析输出。

import subprocess
import re

POWER_MGMT_RE = re.compile(r'IOPowerManagement.*{(.*)}')

def display_status():
    output = subprocess.check_output(
        'ioreg -w 0 -c IODisplayWrangler -r IODisplayWrangler'.split())
    status = POWER_MGMT_RE.search(output).group(1)
    return dict((k[1:-1], v) for (k, v) in (x.split('=') for x in
                                            status.split(',')))

在我的计算机中,屏幕开启时CurrentPowerState的值为4,屏幕关闭时为1

更好的解决方案:使用ctypes直接从IOKit获取该信息。

答案 1 :(得分:3)

我能想到的唯一方法是使用 OSX pmset Power Management CML Tool

  

<强>描述

 pmset changes and reads power management settings such as idle sleep timing, wake on administrative
 access, automatic restart on power loss, etc.

请参阅以下链接,它将提供大量信息,帮助您完成您正在寻找的内容。

http://managingamac.blogspot.com/2012/12/power-assertions-in-python.html

我将包含链接提供的代码,用于“保存和文档”目的:

#!/usr/bin/python

import ctypes
import CoreFoundation
import objc
import subprocess
import time

def SetUpIOFramework():
  # load the IOKit library
  framework = ctypes.cdll.LoadLibrary(
      '/System/Library/Frameworks/IOKit.framework/IOKit')

  # declare parameters as described in IOPMLib.h
  framework.IOPMAssertionCreateWithName.argtypes = [
      ctypes.c_void_p,  # CFStringRef
      ctypes.c_uint32,  # IOPMAssertionLevel
      ctypes.c_void_p,  # CFStringRef
      ctypes.POINTER(ctypes.c_uint32)]  # IOPMAssertionID
  framework.IOPMAssertionRelease.argtypes = [
      ctypes.c_uint32]  # IOPMAssertionID
  return framework

def StringToCFString(string):
  # we'll need to convert our strings before use
  return objc.pyobjc_id(
      CoreFoundation.CFStringCreateWithCString(
          None, string,
          CoreFoundation.kCFStringEncodingASCII).nsstring())

def AssertionCreateWithName(framework, a_type,
                            a_level, a_reason):
  # this method will create an assertion using the IOKit library
  # several parameters
  a_id = ctypes.c_uint32(0)
  a_type = StringToCFString(a_type)
  a_reason = StringToCFString(a_reason)
  a_error = framework.IOPMAssertionCreateWithName(
      a_type, a_level, a_reason, ctypes.byref(a_id))

  # we get back a 0 or stderr, along with a unique c_uint
  # representing the assertion ID so we can release it later
  return a_error, a_id

def AssertionRelease(framework, assertion_id):
  # releasing the assertion is easy, and also returns a 0 on
  # success, or stderr otherwise
  return framework.IOPMAssertionRelease(assertion_id)

def main():
  # let's create a no idle assertion for 30 seconds
  no_idle = 'NoIdleSleepAssertion'
  reason = 'Test of Pythonic power assertions'

  # first, we'll need the IOKit framework
  framework = SetUpIOFramework()

  # next, create the assertion and save the ID!
  ret, a_id = AssertionCreateWithName(framework, no_idle, 255, reason)
  print '\n\nCreating power assertion: status %s, id %s\n\n' % (ret, a_id)

  # subprocess a call to pmset to verify the assertion worked
  subprocess.call(['pmset', '-g', 'assertions'])
  time.sleep(5)

  # finally, release the assertion of the ID we saved earlier
  AssertionRelease(framework, a_id)
  print '\n\nReleasing power assertion: id %s\n\n' % a_id

  # verify the assertion has been removed
  subprocess.call(['pmset', '-g', 'assertions'])

if __name__ == '__main__':
  main()

http://opensource.apple.com/source/PowerManagement/PowerManagement-211/pmset/pmset.c

代码依赖于IOPMLib,IOPMLib用于进行断言,调度电源事件,测量热量等。

https://developer.apple.com/library/mac/#documentation/IOKit/Reference/IOPMLib_header_reference/

要通过Python调用这些函数,我们必须通过IOKit Framework。

http://developer.apple.com/library/mac/#documentation/devicedrivers/conceptual/IOKitFundamentals/

为了让我们在Python中操作C数据类型,我们将使用一个名为ctypes的外部函数接口。

http://python.net/crew/theller/ctypes/

这是作者在页面上描述的包装器;由Michael Lynn撰写。我从上面的作者链接发布的代码是对此代码的重写,以使其更易理解。

https://github.com/pudquick/pypmset/blob/master/pypmset.py