所以我一直被python弄湿了,试图建立一个与gnome通知ui联系在一起的提醒系统。基本思路是,您在remind me to check on dinner in 20 min
之类的shell中键入命令,然后在20分钟内收到桌面通知,提示“晚餐检查”。我这样做的方法是让脚本解析消息,并写出应该发送通知的时间和应该将消息发送到日志文件的时间。
通知是由python守护程序触发的。我正在使用我发现的online守护程序设计。我看到的问题是,当该守护程序运行时,它占用了100%的CPU!我删除了守护程序正在执行的所有代码,当所有守护程序正在执行
时,我仍然遇到此问题while True:
last_modified = os.path.getmtime(self.logfile)
我认为这是一种不好的方法,我应该在有新的提醒时通知守护程序,然后在大多数情况下提醒守护程序应该处于睡眠状态。现在这只是一个想法,但是当我所知道的只是守护进程pid时,我很难找到关于“如何通知进程”的资源。因此,如果我使用time.sleep(time_to_next_notification)
之类的方式暂停了守护程序,是否可以通过一种方式向守护程序发送信号,让它知道有新的提醒?
答案 0 :(得分:2)
尽管我认为您最好使用侦听端口的服务器-客户端类型解决方案,但使用signal
和os
库,您所要求的是100%可能的。这种方法不适用于多线程程序,因为信号仅由python中的父线程处理。另外,Windows不会以相同的方式实现信号,因此选项受到更多限制。
“客户端”进程可以使用os.kill(pid, signal)
发送任意信号。您将必须检查可用的信号,然后确定要使用的信号(signal.NSIG
可能是一个不错的选择,因为它不会影响任何其他默认行为)。
启动时的“守护程序”进程必须注册一个处理程序,以接收到您选择的信号后如何处理。处理程序是必须定义的函数,用于接收接收到的信号本身以及执行程序(def handler(signum, frame):
)的当前堆栈帧。如果您只使用此处理程序做一件事,并且它不需要知道调用它时发生了什么,则可以忽略这两个参数。然后,您必须使用signal.signal
,例如signal.signal(signal.NSIG, handler)
注册处理程序。
从那里,您将想找到一些合适的方法来等到下一个信号,而又不会消耗太多资源。这就像在os.sleep
上循环一样简单
命令,否则您可以尝试获得幻想。我不确定100%从信号处理程序返回后如何恢复执行,因此您可能需要关注递归深度(即,确保您不会在每次处理信号时都递归,否则只会能够在重新启动之前处理有限数量的信号。
让进程在端口(通常称为服务器,但在功能上与“守护程序”描述相同)上侦听而不是侦听操作系统信号,具有几个主要优点。
为了满足一次等待多个流程(侦听输入以及等待下一次通知的需要)的需要,您有很多选择:
信号实际上可能是一个很好的用例,因为signal.SIGALRM
可以用作方便重新设置的闹钟(如果使用的是UNIX)。您将以与以前相同的方式设置处理程序,只需为下一个通知设置警报。设置警报后,您可以简单地继续在端口上侦听新任务。如果有新任务出现,则再次设置警报将覆盖现有警报,因此处理程序将需要检索下一个排队的通知,并在完成第一个任务后重新设置警报。
线程可以用于轮询通知任务队列,也可以创建一个单独的线程来等待每个任务。这不是一个特别优雅的解决方案,但是它将是有效且易于实现的。
最优雅的解决方案可能是使用asyncio
协同例程,但是我对asyncio并不熟悉,并且会承认它们比线程更混乱。