高效的 Python 守护进程

Posted

技术标签:

【中文标题】高效的 Python 守护进程【英文标题】:Efficient Python Daemon 【发布时间】:2011-06-05 23:07:30 【问题描述】:

我很好奇如何在后台运行 python 脚本,每 60 秒重复一次任务。我知道你可以使用 & 在后台添加一些东西,这对这种情况有效吗?

我正在考虑做一个循环,让它等待 60 秒并再次加载,但感觉有些不对劲。

【问题讨论】:

这取决于你想要什么。如果您想安排任务每隔一段时间重复一次,请查看 cron。 【参考方案1】:

在 shell 中使用 & 可能是 Greg 描述的最简单的方法。

如果你真的想创建一个强大的守护进程,你需要查看 os.fork() 命令。

来自Wikipedia的例子:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, time

def createDaemon():
  """ 
      This function create a service/Daemon that will execute a det. task
  """

  try:
    # Store the Fork PID
    pid = os.fork()

    if pid > 0:
      print 'PID: %d' % pid
      os._exit(0)

  except OSError, error:
    print 'Unable to fork. Error: %d (%s)' % (error.errno, error.strerror)
    os._exit(1)

  doTask()

def doTask():
  """ 
      This function create a task that will be a daemon
  """

  # Open the file in write mode
  file = open('/tmp/tarefa.log', 'w')

  # Start the write
  while True:
    print >> file, time.ctime()
    file.flush()
    time.sleep(2)

  # Close the file
  file.close()

if __name__ == '__main__':

  # Create the Daemon
  createDaemon()

然后你可以把你需要的任何任务放在doTask() 块中。

您不需要使用 & 来启动它,它可以让您进一步自定义执行。

【讨论】:

【参考方案2】:

与其编写自己的守护进程,不如使用python-daemon! python-daemon 实现了 PEP 3143 的良好守护进程规范,“标准守护进程库”。

我已经包含了基于该问题的公认答案的示例代码,尽管代码看起来几乎相同,但它有一个重要的根本区别。如果没有python-daemon,您将不得不使用& 将您的进程置于后台,并使用nohup 并防止您的进程在退出shell 时被杀死。相反,当您运行程序时,它会自动与您的终端分离。

例如:

import daemon
import time

def do_something():
    while True:
        with open("/tmp/current_time.txt", "w") as f:
            f.write("The time is now " + time.ctime())
        time.sleep(5)

def run():
    with daemon.DaemonContext():
        do_something()

if __name__ == "__main__":
    run()

实际运行它:

python background_test.py

注意这里没有&

另外,this other *** answer 详细解释了使用python-daemon 的诸多好处。

【讨论】:

您会感到惊讶,但 PEP 作者和库作者是同一个人。所以是的,图书馆很好地实现了 PEP :) 您说“this other *** answer”但链接到一个问题,而不是一个答案。您链接到的问题的选定答案不使用(在此评论时)python-daemon。也许你的意思是***.com/a/688448/117471?【参考方案3】:

我认为您的想法几乎正是您想要的。例如:

import time

def do_something():
    with open("/tmp/current_time.txt", "w") as f:
        f.write("The time is now " + time.ctime())

def run():
    while True:
        time.sleep(60)
        do_something()

if __name__ == "__main__":
    run()

time.sleep(60) 的调用将使您的程序休眠60 秒。当时间到了,操作系统会唤醒你的程序并运行do_something()函数,然后让它重新进入睡眠状态。当您的程序处于休眠状态时,它并没有非常有效地执行任何操作。这是编写后台服务的一般模式。

要从命令行实际运行它,您可以使用 &:

$ python background_test.py &

执行此操作时,脚本的任何输出都将转到与您启动它的终端相同的终端。您可以重定向输出以避免这种情况:

$ python background_test.py >stdout.txt 2>stderr.txt &

【讨论】:

谢谢,这正是我想要的。我所知道的编程的点点滴滴都来自 javascript,然后试图在计时器上做任何事情变成了一场噩梦! 您可能还想查看 nohup(例如 nohup python background_test.py),假设您希望守护程序在您注销后继续运行) 有一种更简单的方法可以使用python-daemon,它是“标准守护进程库”:***.com/a/8375012/462302 @user2452250:请看问题What does if __name__ == “__main__”: do?

以上是关于高效的 Python 守护进程的主要内容,如果未能解决你的问题,请参考以下文章

python基础-守护进程守护线程守护非守护并行

python下编写守护进程

python学习笔记——守护进程

041.Python守护进程,锁信号量和事件

python之守护进程

Python 进程池非守护进程?