如何在Python中捕获系统挂起事件?

8
我正在使用Ubuntu 12.04。有没有一种方法可以用Python捕获暂停事件,即如果笔记本电脑要进入暂停状态,则执行此操作...?同样的问题也适用于捕获关机事件。

1
这涉及到捕获注销事件。但是可能会对您有所帮助:https://dev59.com/W0zSa4cB1Zd3GeqPo7Z0 - theAlse
我会让systemd在暂停期间写入一个文件到/tmp,并在恢复期间写入另一个文件,我的程序将每3至5毫秒轮询一次。此外,如果我的程序访问互联网,我会让网络管理器在暂停和恢复期间创建一个文件,供我的程序轮询。DBUS很复杂。 - WinEunuuchs2Unix
3个回答

6
如果有人遇到相同的问题,这是代码:

#!/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

除了桌面系统之外,其他系统都没有DBus。 - LtWorf
4
从较新版本的upower开始,信号已经移动到systemd logind,新的接口是"org.freedesktop.login1.Manager",新的总线名称是"org.freedesktop.login1",新的信号是"PrepareForSleep",带有一个参数:True表示暂停,False表示恢复。更多信息请参见此处:http://serverfault.com/questions/573379/system-suspend-dbus-upower-signals-are-not-seen - totaam

5

我认为最简单的方法是使用DBUS Python接口并监听'org.freedesktop.UPower'接口上的'AboutToSleep'和/或'Sleeping'事件。


无法找到它,这个问题以前由HALd处理,但现在已经过时了。 - Raber
我把一个shell脚本放在/etc/init.d/目录下,并设置它在关机时运行。这个脚本完成了我想用Python做的工作。虽然我本来希望所有事件都由一个单独的Python程序处理,但现在只能使用不同的脚本了。 - koogee

3
您可以扩展此代码,它监听来自acpid的事件,尝试仅打印其接收到的字符串并生成所需的事件,以查看该字符串的样式。
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

谢谢,这正是我在寻找的。顺便问一下,在哪里可以获得这些代码的含义列表?例如:000000081? - koogee
老实说,我也不知道,我是通过生成事件并查看字符串的形式得到这些信息的。你可以尝试查看 acpid 的文档,它是发送这些字符串的守护进程。 - LtWorf
这很奇怪。似乎在挂起/恢复后,我只收到一个盖子打开/关闭信号。['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'] - koogee
也许另一个事件没有生成为ACPI事件,或者不在您的笔记本电脑上,或者如果您在关闭盖子时挂起,当您打开它时仍然处于挂起状态,您会失去该事件。 - LtWorf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接