【问题标题】:How to use Daemon that has a while loop? [duplicate]如何使用有while循环的守护进程? [复制]
【发布时间】:2013-11-05 05:09:27
【问题描述】:

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

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

 main.py

     def requestData(information):
         return currently_crunched_data()

     while True:
          crunchData()

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

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

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

【问题讨论】:

  • 我推荐使用 supervisord - 它避免了处理守护进程问题的需要。
  • 这里有两个单独的问题。首先,有“我如何同时做两件事”,是的,使用后台线程是一种明显的方法,并且会起作用。然后是“我如何在 Python 中编写守护程序”,这是一个重复。所以,我将忽略第二个。
  • 对不起,我已经知道如何用 Python 写一个 Daemon:doc.uh.cz/Python/Pyro-3.1/8-example.html 问题是 Daemon 本身是一个 while 循环,而我的进程是一个 while 循环。
  • 是的,我正在使用 Linux,但希望有一个通用的解决方案
  • @KingofGames:很好,那么我忽略了正确的部分并回答(我希望)正确的部分。 :)

标签: python


【解决方案1】:

已经有很多关于在 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(这使得在两个进程之间共享或传递数据稍微复杂一些,但仍然不算太糟糕)。

【讨论】:

    猜你喜欢
    • 2012-10-19
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 2011-07-20
    • 2014-07-07
    • 1970-01-01
    • 2012-02-20
    相关资源
    最近更新 更多