How can I catch a system suspend event in Python?
Asked Answered
O

3

8

I'm using ubuntu 12.04. Is there a way to catch a suspend event in Python, i.e. if the laptop is going to suspend, do this...? The same question for catching shutdown event.

Oke answered 23/11, 2012 at 10:45 Comment(2)
This deals with catching log-out event. but may help you: #2490666Harm
I would have systemd write out a file to /tmp during suspend and a different file during resume which my program would poll every 3 to 5 deciseconds. Additionally if my program accessed internet I would have network manager create a file during suspend and resume which my program would poll. DBUS is "complicated".Yettie
B
5

i think simplest method would be to use DBUS python interface and listen for 'AboutToSleep' and/or 'Sleeping' event on 'org.freedesktop.UPower' interface

Brathwaite answered 23/11, 2012 at 13:9 Comment(2)
cannot find it as well, this used to be handled by HALd, but it is obsolete nowBrathwaite
i placed a shell script in /etc/init.d/ and set it to run during shutdown. The script does the work that i wanted to do in python. I would've liked all events handled in a single python program but i'll settle for using different scripts.Oke
O
6

If some one stumbles on the same problem, here's the code:

#!/usr/bin/env python

import dbus      # for dbus communication (obviously)
import gobject   # main loop
from dbus.mainloop.glib import DBusGMainLoop # integration into the main loop

def handle_resume_callback():
    print "System just resumed from hibernate or suspend"

def handle_suspend_callback():
    print "System about to hibernate or suspend"

DBusGMainLoop(set_as_default=True) # integrate into main loob
bus = dbus.SystemBus()             # connect to dbus system wide
bus.add_signal_receiver(           # defince the signal to listen to
    handle_resume_callback,            # name of callback function
    'Resuming',                        # singal name
    'org.freedesktop.UPower',          # interface
    'org.freedesktop.UPower'           # bus name
)

bus.add_signal_receiver(           # defince the signal to listen to
    handle_suspend_callback,            # name of callback function
    'Sleeping',                        # singal name
    'org.freedesktop.UPower',          # interface
    'org.freedesktop.UPower'           # bus name
)

loop = gobject.MainLoop()          # define mainloop
loop.run()                         # run main loop
Oke answered 25/11, 2012 at 6:57 Comment(2)
except that only desktop systems have dbusMarriage
Starting with newer versions of upower, the signal has moved to systemd logind, the new interface is "org.freedesktop.login1.Manager", the new bus name is "org.freedesktop.login1" and the new signal is "PrepareForSleep" with an argument: True for suspending, False for resuming. More info here: serverfault.com/questions/573379/…Picklock
B
5

i think simplest method would be to use DBUS python interface and listen for 'AboutToSleep' and/or 'Sleeping' event on 'org.freedesktop.UPower' interface

Brathwaite answered 23/11, 2012 at 13:9 Comment(2)
cannot find it as well, this used to be handled by HALd, but it is obsolete nowBrathwaite
i placed a shell script in /etc/init.d/ and set it to run during shutdown. The script does the work that i wanted to do in python. I would've liked all events handled in a single python program but i'll settle for using different scripts.Oke
M
3

You can extend this code, it listens for events from acpid, try to just print the string it receives and generate the event you want and see what the string looks like.

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/var/run/acpid.socket")
print "Connected to acpid"
while 1:
    for event in s.recv(4096).split('\n'):
        event=event.split(' ')
        if len(event)<2: continue
        print event
        if event[0]=='ac_adapter':
            if event[3]=='00000001': #plugged
                plugged() #Power plugged event
            else: #unplugged
                unplugged() #Power unplugged event
        elif event[0]=='button/power':
            power_button() #Power button pressed
        elif event[0]=='button/lid':
            if event[2]=='open':
                lid_open() #Laptop lid opened
            elif event[2]=='close':
                lid_close() #Laptop lid closed
Marriage answered 23/11, 2012 at 13:42 Comment(4)
thanks. its what i was looking for. btw where can you get a list of what these codes mean? e.g. 000000081?Oke
Hm no idea honestly, i got those by generating the events and see what the string looked like, you might try to see in the documentation of acpid, which is the daemon sending those strings.Marriage
this is strange. It seems i'm getting only one of the lid open/close signals after a suspend/resume. ['processor', 'CPU0', '00000081', '00000000'] ['button/lid', 'LID0', '00000080', '00000003'] ['processor', 'CPU0', '00000081', '00000000'] ['ac_adapter', 'ADP0', '00000080', '00000000'] ['battery', 'BAT0', '00000080', '00000001'] ['processor', 'CPU0', '00000081', '00000000']Oke
Maybe the other one is not generated as ACPI event, or not on your laptop, or if you suspend on closing the lid, when you open it's still suspended and you loose the event.Marriage

© 2022 - 2024 — McMap. All rights reserved.