为了账号安全,请及时绑定邮箱和手机立即绑定

如何在给定 pid 的情况下通知守护进程

如何在给定 pid 的情况下通知守护进程

动漫人物 2021-10-12 10:14:16
所以我一直在用 python 弄湿我的脚,试图构建一个与 gnome 通知 ui 相关的提醒系统。基本思想是你在你的 shell 中输入一个命令remind me to check on dinner in 20 min,然后在 20 分钟内你会收到一个桌面通知,上面写着“检查晚餐”。我这样做的方法是让脚本解析消息并写入应该发送通知的时间以及应该发送到日志文件的消息。通知由 python 守护进程触发。我正在使用我在网上找到的这个守护进程设计。我看到的问题是当这个守护进程运行时,它占用了我 100% 的 CPU!我剥离了守护进程正在做的所有代码,当所有守护进程正在做的时候,我仍然有这个问题while True: last_modified = os.path.getmtime(self.logfile)我认为这是一种糟糕的方法,我应该在有新提醒时通知守护程序,然后大部分时间提醒守护程序应该处于睡眠状态。现在这只是一个想法,但是当我只知道守护进程 pid 时,我很难找到有关“如何通知进程”的资源。因此,如果我用类似time.sleep(time_to_next_notification)的方式暂停了守护进程,是否有办法向守护进程发送信号,让它知道有新的提醒?
查看完整描述

1 回答

?
森林海

TA贡献2011条经验 获得超2个赞

尽管我相信您最好使用侦听端口的服务器 - 客户端类型的解决方案,但您要问的是 100% 可能使用signalos库。这种方法不适用于多线程程序,但是因为信号仅由 python 中的父线程处理。此外,windows 不会以相同的方式实现信号,因此选项更加有限。

信号

“客户端”进程可以使用os.kill(pid, signal). 您必须查看可用信号并确定要使用哪个信号(signal.NSIG可能是一个不错的选择,因为它不应该影响任何其他默认行为)。

启动时的“守护进程”进程必须注册一个处理程序,以便在它接收到您选择的信号时执行什么操作。处理程序是一个您必须定义的函数,它接收接收到的信号本身以及 executon ( def handler(signum, frame):)的当前堆栈帧。如果你只用这个处理程序做一件事,并且它不需要知道它被调用时发生了什么,你可以忽略这两个参数。然后您必须使用signal.signalex:注册处理程序signal.signal(signal.NSIG, handler)

从那里你会想找到一些合适的方法来等待下一个信号而不消耗太多资源。这可以像循环os.sleep 命令一样简单,或者您可以尝试变得花哨。我不确定 100% 从信号处理程序返回时如何恢复执行,因此您可能需要关注递归深度(即,确保每次处理信号时都不要递归,否则您将永远能够在需要重新启动之前处理有限数量的信号)。

服务器

让进程监听端口(通常称为服务器,但在功能上与您的“守护进程”描述相同)而不是监听操作系统信号有几个主要优点。

  • 端口能够在信号只能触发事件的地方发送数据

  • 端口更相似跨平台

  • 端口在多线程中玩得很好[r]

  • 端口使通过网络发送消息变得容易(即:从手机创建提醒并在 PC 上执行)

一次等待多件事

为了解决同时等待多个进程的需要(侦听输入以及等待发送下一个通知),您有很多选择:

  • 信号实际上可能是一个很好的用例,因为signal.SIGALRM它可以用作方便地重新设置的闹钟(如果您使用的是 UNIX)。您可以像以前一样设置处理程序,只需为下一个通知设置警报。设置警报后,您可以简单地继续在端口上侦听新任务。如果有新任务进入,再次设置警报将覆盖现有任务,因此处理程序需要检索下一个排队通知并在第一个任务完成后重新设置警报。

  • 线程既可以用于轮询通知任务队列,也可以创建一个单独的线程来等待每个任务。这不是一个特别优雅的解决方案,但它会有效且易于实施。

  • 最优雅的解决方案可能是使用asyncio协程,但是我对 asyncio 不太精通,并且承认它们比线程更令人困惑。


查看完整回答
反对 回复 2021-10-12
  • 1 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信