我在Debian上运行单线程Python 2.7守护程序/服务。我有一些禁用某些硬件功能的关键清理代码。
import sys
import atexit
import signal
from my_job import give_high_fives
from my_cleanup import prevent_the_apocalypse
atexit.register(prevent_the_apocalypse)
signal.signal(signal.SIGTERM, prevent_the_apocalypse)
signal.signal(signal.SIGHUP, prevent_the_apocalypse)
try:
while True:
give_high_fives()
finally:
prevent_the_apocalypse()
这看起来很偏执,我也不喜欢多次调用清理代码。现在,看起来清理在SIGTERM
上被称为3或4次。
在所有可能的退出条件下,prevent_the_apocalypse
只有一种方法可以完成一次吗?
答案 0 :(得分:6)
在Python中编写正确的守护进程很难。事实上,任何语言都很难。 PEP 3143解释了这些问题。
daemon
模块包含了大部分细节,因此您不必将它们弄清楚。如果使用它,则添加清理代码变得非常容易。
一个选项是将daemon.DaemonContext
子类化并将其放在那里。例如:
class MyDaemonContext(daemon.DaemonContext):
def close(self):
if not self.is_open:
return
prevent_the_apocalypse()
super(MyDaemonContext, self).close()
with MyDaemonContext():
while True:
give_high_fives()
daemon
模块已经设置了信号处理程序,以便它们执行您已配置的操作,但不会跳过close
方法。 (close
将在上下文__exit__
,atexit
方法中运行一次,或者可能在其他地方运行。{/ p>
如果你想要更复杂的东西,有些信号会跳过close
而其他信号却没有,而不是子类化,只需适当地设置signal_map
。
答案 1 :(得分:-1)
让您的信号处理程序除了将全局变量设置为true之外什么也不做。然后在主循环中检查该变量,如果它是真的则跳出,在退出时运行清理处理程序。