Remind-You Part1. 多进程控制

来源:互联网 发布:java的输入输出流 编辑:程序博客网 时间:2024/06/06 03:08

原理说明

在Remind-You中,每个plugin都对应着一个进程。主进程在启动后,从配置文件中读取当前有多少个插件。并依次启动这些插件。后续plugin进程退出后,主进程都会重新生成plugin进程。

代码位置

可以在github上找到第一天的代码。https://github.com/bymzy/remind-you/tree/day1

文件结构

[root@bymzy remind-you]# tree.├── __init__.py├── main.py├── plugins│   ├── conf.json│   ├── dict_plugin.py│   ├── dict_plugin.pyc│   ├── __init__.py│   └── __init__.pyc├── scheduler.py├── scheduler.pyc└── setup.py

在第一天的工作中,比较重要的文件有,main.py, scheduler.py, dict_plugin.py以及conf.json。启动conf.json需要被拷贝到/etc/scheduler.py。

依赖的环境及库

使用python2.7运行。

  • mulitprocessing
    该库提供了方法,可以一某个函数为目标,生成一个进程执行。返回的进程对象,的start方法用来启动该进程;is_alive方法用来判断进程是否已经退出。
    process = multiprocessing.Process(target=func, args=(arg))process.start()process.is_alive()
  • importlib
    在Remind-You中,需要支持动态的添加插件。使用importlib可以根据字符串导入lib。
    module = importlib('dict_plugin.py')

主要代码

CONF_FILE = '/etc/scheduler.conf'def parse_config(conf):    with open(conf, 'r') as f:        data = f.read()        return json.loads(data)def run_plugin(plugin):    name = plugin.get('name')    fileName = plugin.get('fileName')    desc = plugin.get('desc')    arg = plugin.get('args')    module = importlib.import_module('plugins.' + fileName)    process = multiprocessing.Process(target=module.run, args=(arg,))    process.start()    return processdef scheduler_loop():    print 'main process pid: %u' % os.getpid()    conf_dict = parse_config(CONF_FILE)    process_list = []    for plugin in conf_dict.get('plugins', []):        process_list.append((plugin, run_plugin(plugin)))    # monitor process     while True:        to_add = []        to_del = []        for proc in process_list:            if not proc[1].is_alive():                proc[1].join()                to_add.append((proc[0], run_plugin(proc[0])))                to_del.append(proc)        for proc in to_del:            process_list.remove(proc)            to_del = []        for proc in to_add:            process_list.append(proc)            to_add = []        time.sleep(2)

dict_plugin.py 代码示例

import timeimport osimport requestsdef run(args):    print 'my pid is: %u ' % os.getpid()    time.sleep(3)

plugin代码比较简单,只有一个run函数打印自己的pid,然后等待3s退出。这样做事为了模拟,主进程将plugin进程拉起的情况。

配置文件示例

{    "plugins": [        {               "name": "dict",            "desc": "help you remember English words",            "fileName": "dict_plugin",            "args": "test"        }       ]   }

代码说明

  • 在main.py中,执行scheduler_loop()方法。这个方法首先从配置文件中读取所有的插件。当前只有一个dict插件,插件fileName字段描述有该插件代码所在的文件,插件代码中默认的run函数为插件的运行函数。
  • 使用importlib将插件import进主进程,然后使用multiprocessing.Process生成一个新的进程并调用Start启动。
  • 主进程当前页比较简单,循环的判断插件进程是否退出。如果退出,则继续生成一个插件进程。

最终执行效果如下

执行main.py后,插件进程定时退出,然后重新被拉起。


remind-you-day1.PNG