python库介绍-python-daemon: 实现python后台程序的工具

简介

python-daemon实现Unix守护进程。 参考:PEP 3143

该库实现了PEP 3143“标准守护进程库”的良好行为守护进程规范。

DaemonContext实例保存程序的行为和配置的进程环境。

快速入门


import time

with daemon.DaemonContext():
    f = open("/tmp/test.log",'w')
    while True:
        f.write('''
        Library to implement a well-behaved Unix daemon process.

This library implements the well-behaved daemon specification of PEP 3143, “Standard daemon process library”.

A well-behaved Unix daemon process is tricky to get right, but the required steps are much the same for every daemon program. A DaemonContext instance holds the behaviour and configured process environment for the program; use the instance as a context manager to enter a daemon state.
''')
        f.write("{0}\n".format(time.ctime(time.time())))
        time.sleep(1)

执行:


$ python3 daemon1.py 

$ tail -f /tmp/test.log 
This library implements the well-behaved daemon specification of PEP 3143, “Standard daemon process library”.

A well-behaved Unix daemon process is tricky to get right, but the required steps are much the same for every daemon program. A DaemonContext instance holds the behaviour and configured process environment for the program; use the instance as a context manager to enter a daemon state.
Thu Feb  8 14:21:43 2018

$ ps afx | grep -i daemon1
 8646 pts/2    S+     0:00          |           \_ grep --color=auto -i daemon1
 8640 ?        S      0:00          \_ python3 daemon1.py
$ kill -9 8640

要想停止上述进程,可以通过ps查找到进程号,然后kill。

注意上述代码在python2没有任何问题,不过在python需要修改库文件runner.py打开文件的方式。


# vi /usr/local/lib/python3.5/dist-packages/daemon/runner.py 
# 118 -120
        self.daemon_context = DaemonContext()
        self.daemon_context.stdin = open(app.stdin_path, 'wb+',buffering=0)
        self.daemon_context.stdout = open(app.stdout_path,  'wb+',buffering=0)
        self.daemon_context.stderr = open(
                app.stderr_path, 'wb+', buffering=0)

更实用的例子

#讨论钉钉免费群21745728qq群144081101 567351477
import time
import logging
import logging.handlers
from daemon import runner

class App():
    
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/foo.pid'
        self.pidfile_timeout = 5
        
    def run(self):
        
        logs = logging.getLogger('MyLogger')
        logs.setLevel(logging.DEBUG)
        fh = logging.handlers.RotatingFileHandler(
            '/tmp/test.log',maxBytes=10000000,backupCount=5)
        fh.setLevel(logging.DEBUG)
        formatter = logging.Formatter(u'%(asctime)s [%(levelname)s] %(message)s')
        fh.setFormatter(formatter)
        logs.addHandler(fh)  
        
        while True:
            for i in range(10):
                logs.info("Beginning Scan {0}! \n".format(i))
            time.sleep(1)

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

执行:


$ python2 daemon2.py 
usage: daemon2.py start|stop|restart

$ python3 daemon2.py  start
andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ 
andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 77, in acquire
    write_pid_to_pidfile(self.path)
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 161, in write_pid_to_pidfile
    pidfile_fd = os.open(pidfile_path, open_flags, open_mode)
FileExistsError: [Errno 17] File exists: '/tmp/foo.pid'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "daemon2.py", line 39, in <module>
    daemon_runner.do_action()
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 274, in do_action
    func(self)
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 182, in _start
    self.daemon_context.open()
  File "/usr/local/lib/python3.5/dist-packages/daemon/daemon.py", line 389, in open
    self.pidfile.__enter__()
  File "/usr/local/lib/python3.5/dist-packages/lockfile/__init__.py", line 197, in __enter__
    self.acquire()
  File "/usr/local/lib/python3.5/dist-packages/daemon/pidfile.py", line 60, in acquire
    super(TimeoutPIDLockFile, self).acquire(timeout, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 85, in acquire
    self.path)
lockfile.LockTimeout: Timeout waiting to acquire lock for /tmp/foo.pid

andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ python3 daemon2.py  stop
Terminating on signal 15
andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ python3 daemon2.py  stop
Traceback (most recent call last):
  File "daemon2.py", line 39, in <module>
    daemon_runner.do_action()
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 274, in do_action
    func(self)
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 224, in _stop
    raise error
daemon.runner.DaemonRunnerStopFailureError: PID file '/tmp/foo.pid' not locked

注意上面的错误是重复启动或者停止时进程并不存在导致的。

参考资料

老式书写后台进程的一种方式


import time
import logging
import logging.handlers


logs = logging.getLogger('MyLogger')
logs.setLevel(logging.DEBUG)
fh = logging.handlers.RotatingFileHandler(
    '/tmp/test.log',maxBytes=10000000,backupCount=5)
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter(u'%(asctime)s [%(levelname)s] %(message)s')
fh.setFormatter(formatter)
logs.addHandler(fh)  


while True:
    for i in range(10):
        logs.info("Beginning Scan {0}! \n".format(i))
    time.sleep(1)      

这样并不能后台执行,但是可以借助linux的nohup和&。为此添加如下的启动和停止脚本,其实也不麻烦:

shell脚本参见: http://t.cn/R8scWAe


$ sh startup.sh 
================================================================================================================
Starting older.py(PID=15315)...[Success]
================================================================================================================
$ sh startup.sh 
================================================================================================================
older.py already started(PID=15315)
================================================================================================================
$ sh shutdown.sh 
================================================================================================================
Stopping older.py(PID=15315)...[Success]
================================================================================================================
$ sh shutdown.sh 
================================================================================================================
older.py is not running
================================================================================================================

其他

supervisord 可以linux控制linux进程,当然也可以后台化。

How do you create a daemon in Python?

另外也可以向linux systemd注册为后台进程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,431评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,637评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,555评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,900评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,629评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,976评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,976评论 3 448
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,139评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,686评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,411评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,641评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,129评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,820评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,233评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,567评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,362评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,604评论 2 380

推荐阅读更多精彩内容