1

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

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

 main.py

     def requestData(information):
         return currently_crunched_data()

     while True:
          crunchData()

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

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

我目前正在研究 Pyro 来做到这一点。有谁知道我如何最终使后台运行 while 循环能够接收来自其他进程的请求(比如我想的守护进程)?

4

1 回答 1

2

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

那么,你如何让你的守护进程做后台工作呢?

正如您所怀疑的,线程是一个明显的答案。但存在三种可能的复杂性。


首先,有关机。如果幸运的话,您的crunchData函数可以随时被立即终止,而不会损坏数据或(太重要)丢失工作。在这种情况下:

def worker():
    while True:
        crunchData()

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

请注意t.daemon. “守护线程”与您的程序是守护进程无关;这意味着您可以退出主进程,它会被立即杀死。

但如果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.

根据您的用例,a Queue、文件或其他内容可能更简单。


最后,crunchData大概是做了大量的CPU工作。您需要确保请求处理程序只做很少的 CPU 工作,否则每个请求都会使事情变慢,因为两个线程争夺 GIL。通常这没有问题。如果是,请使用 amultiprocessing.Process而不是 a Thread(这使得在两个进程之间共享或传递数据稍微复杂一些,但仍然不算太糟糕)。

于 2013-10-25T23:18:17.120 回答