7

如何检查屏幕是否由于 Mac/Python 下系统偏好设置中的节能设置而关闭?

4

2 回答 2

6

快速而肮脏的解决方案:调用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(',')))

在我的电脑中, 的值CurrentPowerState4屏幕打开和1屏幕关闭的时间。

更好的解决方案:用于ctypes直接从IOKit.

于 2013-01-17T02:55:47.883 回答
4

我能想到的唯一方法是使用OSX pmset 电源管理 CML 工具

描述

 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,它的功能是做出断言、安排电源事件、测量热量等等。

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

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

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

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

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

这是作者在页面上描述的包装器;由迈克尔林恩撰写。我从上面的作者链接中发布的代码是对该代码的重写,以使其更易于理解。

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

于 2013-01-14T01:39:16.690 回答