如何使用具有while循环的守护进程?

时间:2013-10-25 23:07:23

标签: python

我是Daemons的新手,我想知道如何让我的主脚本成为守护进程?

我有我的主要脚本,我希望制作一个守护进程并在后台运行:

 main.py

     def requestData(information):
         return currently_crunched_data()

     while True:
          crunchData()

我希望能够在循环运行时对此守护进程使用requestData函数。我不太熟悉守护进程或如何将我的脚本转换成一个。

但是我猜我必须创建两个线程,一个用于我的cruncData循环,另一个用于守护进程请求接收器,因为守护进程有自己的循环(daemon.requestLoop())。

我目前正在调查Pyro这样做。有没有人知道如何最终使后台运行,而循环有能力接收来自其他进程的请求(比如我想的守护进程)?

1 个答案:

答案 0 :(得分:2)

关于在Python中创建守护进程已经有很多问题,例如this one,它很好地回答了这一部分。

那么,你如何让你的守护进程做背景工作?

如您所料,线程是一个明显的答案。但有三种可能的复杂性。


首先,关机了。如果你很幸运,你的crunchData函数可以在任何时候被立即杀死,没有损坏的数据或(过于重要的)丢失的工作。在那种情况下:

def worker():
    while True:
        crunchData()

# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.daemon = True
t.start()

请注意t.daemon"daemon thread"与您的程序作为守护程序无关;这意味着你可以退出主进程,它将被立即杀死。

但如果crunchData无法被杀死怎么办?然后你需要做这样的事情:

quitflag = False
quitlock = threading.Lock()

def worker():
    while True:
        with quitlock:
            if quitflag:
                return
        crunchData()

# ... somewhere in the daemon startup code ...
t = threading.Thread(target=worker)
t.start()

# ... somewhere in the daemon shutdown code ...
with quitlock:
    quitflag = True
t.join()

我假设crunchData的每次迭代都不会花那么长时间。如果是,您可能需要在功能本身内定期检查quitFlag


同时,您希望您的请求处理程序访问后台线程正在生成的一些数据。你也需要某种同步。

显而易见的是只使用另一个Lock。但crunchData很有可能经常写入其数据。如果它一次保持锁定10秒,请求处理程序可能会阻塞10秒钟。但如果它抓住并释放锁一百万次,那可能需要比实际工作更长的时间。

另一种方法是对数据进行双重缓冲:将crunchData写入新副本,然后在完成后,暂时抓住锁定并设置currentData = newData

根据您的使用情况,Queue,文件或其他内容可能更简单。


最后,crunchData可能会做很多CPU工作。您需要确保请求处理程序执行非常少的CPU工作,或者每个请求会因为两个线程争夺GIL而减慢速度。通常这没问题。如果是,请使用multiprocessing.Process而不是Thread(这使得在两个进程之间共享或传递数据稍微复杂一些,但仍然不会太糟糕)。