高效的Python守护进程
我很好奇怎么能在后台运行一个Python脚本,让它每60秒重复执行一个任务。我知道可以用&符号把某个东西放到后台,这样做在这种情况下有效吗?
我在想用一个循环,让它等60秒再重新执行,但感觉这样做有点不太对劲。
3 个回答
在命令行中使用 & 是最简单的方法,就像 Greg 说的那样。
不过,如果你想创建一个功能强大的后台程序(Daemon),你就需要了解一下 os.fork() 这个命令。
这里有个来自 维基百科 的例子:
#!/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()
这个块里面。
这样你就不需要用 & 来启动它了,而且可以让你进一步自定义执行的方式。
与其自己写一个守护进程,不如使用python-daemon!这个库遵循了PEP 3143的标准守护进程规范,也就是“标准守护进程库”。
我提供了一个示例代码,基于这个问题的接受答案。虽然代码看起来几乎一模一样,但它有一个重要的根本区别。如果没有python-daemon,你需要使用&
把你的进程放到后台,还要用nohup
来防止在退出终端时进程被杀掉。而使用这个库时,程序运行时会自动与终端分离。
例如:
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
注意这里没有&
。
另外,这个StackOverflow的其他回答详细解释了使用python-daemon的许多好处。
我觉得你的想法基本上就是你想要的。举个例子:
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 &