我有一个长时间运行的python进程在raspberrypi(控制花园)上无头运行,如下所示:
from time import sleep
def run_garden():
while 1:
/* do work */
sleep(60)
if __name__ == "__main__":
run_garden()
60秒的睡眠时间是我花园里发生任何变化的充足时间(湿度,气温,打开泵,关闭风扇等),但如果我想手动覆盖这些东西怎么办?
目前,在我的/* do work */
循环中,我首先呼叫另一台服务器,我保留配置变量,我可以通过Web控制台更新这些配置变量,但它缺乏任何实时感觉,因为它依赖于60秒循环(例如,您可能会更新Web控制台,然后等待45秒以使所需效果生效)
运行run_garden()
的raspberryPi专门用于花园,它基本上是唯一占用资源的东西。所以我知道我有空间做某事,我只是不知道是什么。
一旦循环发现config var已被更新的事实,循环就可以进行指数退避以继续检查交互,而不是等待60秒,但它只是觉得这样做好得多。
有没有更好的方法可以基本进入这个漫长的过程?
答案 0 :(得分:1)
为什么不使用基于事件的循环而不是在一段时间内休眠。
这样你的循环只会在检测到变化时运行,并且在检测到变化时总会运行(这是你问题的关键点?)。
你可以使用以下方式做这件事:
python event objects
等待触发一个或所有事件对象并运行循环。您还可以等待X事件等等,具体取决于您是否希望更新一个变量。
甚至像以下系统: broadcasting events
答案 1 :(得分:1)
收听主循环中的套接字。在套接字读取调用上使用超时(例如60秒,应该执行下一次更新花园的时间),这样当没有命令进入时,至少每分钟都会恢复正常功能。
如果您需要花园时间更新更快而不是每分钟都需要检查自上次更新以来的时间,因为当 >时,读取调用将显着加快em>命令进来。
答案 2 :(得分:1)
Python的select
模块听起来可能会有所帮助。
如果您曾经使用过unix模拟(例如在套接字编程中可能?),那么它会很熟悉。
如果没有,here is the select
section of a C sockets reference I often recommend。并here is what looks like a nice writeup of the module。
警告:第一个引用是专门针对C而不是Python,但select
系统调用的概念是相同的,因此讨论可能会有所帮助。
基本上,它允许您告诉它您感兴趣的事件(例如,套接字数据到达,键盘事件),并且它将永久阻止,或者直到您指定的超时为止。
如果您正在使用套接字,那么将套接字和stdin添加到您感兴趣的事件列表中很容易。如果您正在寻找一种“有条件地睡眠”60秒的方法,除非/直到检测到按键,这也会起作用。
修改强>:
解决此问题的另一种方法是让您的raspberry-pi“注册”运行Web控制台的服务器。这可能需要一些额外的工作,但它会给你你正在寻找的实时效果。
基本上,raspberry-pi通过向服务器提醒自身来“注册”自己,并且服务器存储设备的地址。如果使用TCP,您可以保持连接打开(如果您有防火墙可以处理,这可能很重要)。如果使用UDP,您可以在注册之前绑定设备上的端口,允许服务器响应“通知”的源地址。
一旦宣布,配置时。选项在服务器上发生变化,通常会发生以下两种情况之一:
A)您向设备发送微小的“ping”(一般意义上,而不是ICMP主机检测协议),提醒它配置选项已更改。此时主机会立即请求完整配置。设置,用它获取更新。
B)您发送更新的配置。选项(或整个配置。设置)返回设备。这减少了设备和服务器之间的消息数量,但可能需要更多工作,因为它似乎更偏离您当前的设置。