10.5: A python script to work around a sleep issue

Dec 23, '07 10:30:01AM

Contributed by: Anonymous

After installing Leopard, my iMac would no longer auto sleep. It worked flawlessly in Tiger. I searched google and found many others having similar problems. I found many different fixes, such as removing the PowerManagement plist file, unplugging all devices, and not running certain widgets or programs. However, no matter what I did, it would not auto sleep. It would stay asleep if I manually put it to sleep.

I called Apple and was on the phone with them for about two hours before they said it is probably a hardware problem, thanks for calling. After all that hassle, I decided to see if AppleScript could put it to sleep, and it did. Once I found that out, I just wrote a python program that keeps track of how long the screen saver is running. Using that, it determines if the system has been unused for the period the user set in system preferences for machine sleep.

import sys, os, shutil, filecmp, string, datetime, time

# initalize some variables
cronPeriod = 1
sleepFile = "/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist"
saverFile = os.path.join(os.getenv("HOME")) + '/Library/Preferences/ByHost/com.apple.screensaver.0016cb98e9e2'
trackingFile = os.path.join(os.getenv("HOME")) + '/var/sleepTracker'

f = open(sleepFile, "r")
useNextLine = 0
for line in f.readlines():
  if useNextLine == 1:
    useNextLine = 0
    timeLine = line.strip()
  if line.strip() == "<key>System Sleep Timer</key>":
    useNextLine = 1
f.close()

sleepTime = timeLine.strip('<integer>')
sleepTime = sleepTime.strip('</')
sleeepTime = int(sleepTime)

screensaverTime = os.popen("defaults read " + saverFile + " idleTime")
screensaverTime =  screensaverTime.read()

sleepTime = int(sleepTime) * 60 - int(screensaverTime)
if sleepTime < 0:
  sleepTime = 0


########################################
# Begin function definations
######################################## 
# checkFiles is the function that checks the times
# of the tracking file

def clearFile():
  if os.path.exists(trackingFile):
    os.remove(trackingFile)
  cmd = "touch " + trackingFile
  os.system(cmd)

def compareTimes():
  endLine = ""
  currentTime = time.mktime(datetime.datetime.now().timetuple())
  currentTime = str(currentTime).split('.')[0]

  f = open(trackingFile, "r")
  data = f.read()
  f.close()
  lines = data.split("n")
  lastRunning = lines[len(lines)-2]
  lastRunning = lastRunning.split('.')[0]

  if lastRunning == "":
    print "last time is: " + lastRunning
    return

  difference = int(currentTime) - int(lastRunning)
  print time.localtime()
  print "difference between current time and last time saver was found running is: ", difference
 
  cronPeriodSec = int(cronPeriod * 1.5 * 60)
  print time.localtime()
  print "cron period is: ", cronPeriodSec

  if difference > cronPeriodSec:
    print time.localtime()
    print "difference is greater - need to clear file"
    clearFile()

def wantSleep(currentTime):
  f = open(trackingFile, "r")
  data = f.read()
  f.close()
  lines = data.split("n")
  firstRunning = lines[0]
  firstRunning = firstRunning.split('.')[0]

  if firstRunning == "":
    #print "firstRunning was blank"
    return

  print "current time is: ", currentTime, " first time is: ", firstRunning
  difference = int(currentTime) - int(firstRunning)
  print time.localtime()
  print "difference between now and first time screensaver was on is: ", difference
  print "comparing against: ", int(sleepTime) 

  if difference >= sleepTime:
    print time.localtime()
    print "sleep is desired" 
    aplcmd = 'tell app "Finder" to sleep'
    cmd = "/usr/bin/osascript -e " + "'" + aplcmd + "'"
    print time.localtime()
    print cmd
    os.system(cmd)
 
##############################################
# End function definations
#############################################

#check if the screensaver is running:
cmd = "ps -e | grep ScreenSaverEngine | grep -v grep"
result = os.system(cmd)

#print "remove the following line to run for real"
#result = 234

if result != 256:
  print time.localtime()
  print "Screen Saver is running"
  compareTimes()

  currentTime = time.mktime(datetime.datetime.now().timetuple())
  currentTime = str(currentTime).split('.')[0]
  f = open(trackingFile, 'a')
  f.write(currentTime + "n")
  f.close

  wantSleep(currentTime)

else:
  print time.localtime()
  print "Screen Saver Not running"
  clearFile()

sys.exit(1)
I put this in cron to run once a minute and it has been working very reliably. Note: I didn't make it robust enough to find the screensaver preferences file. I hard-coded it to mine, so if anyone wants to try it, you would need to update the numbers at the end of the saverFile value.

[robg adds: I haven't tested this one.]

Comments (3)


Mac OS X Hints
http://hints.macworld.com/article.php?story=20071220142440219