说明
我们通常会在系统功能上线后需要修改某一部分的内容,但是我们又不希望重新启动整个系统。以下基于这个应用进行介绍。
方法:通过imp的reload函数进行「模块」的重载
内容
首先要区别python里面模块和包的概念,具体的可以参考这篇文章
在Python中,一个.py文件就称之为一个模块(Module)。
Python又引入了按目录来组织模块的方法,称为包(Package)。包可以理解为一个文件夹,里面有若干.py文件,并且有一个__init__.py文件
注意:我们引用的函数是存在模块里的,要对对应的模块重载(而不是包)
例子
包的重载实验
├── entry_flask.py
└── task_pack
├── __init__.py
└── task1.py
在entry_flask.py
中构建了一个简单的服务(不使用debug模式),其中whoami和index只是为了维持一个规范写的,不用去看。主要有两个函数与本例有关:reload_module
和tasks
。
from flask import Flask, request, jsonify
from imp import reload
# import aa as tpack
import task_pack as tpack
# 初始化app
app = Flask(__name__)
@app.route('/whoami/', methods=['GET', 'POST'])
def whoami():
pass
@app.route('/', methods=['GET', 'POST'])
def index():
return 'Hello , I am Server'
# 好像只能按模块reload
@app.route('/reload_module/<task_name>',methods=['GET', 'POST'])
def reload_module(task_name):
reload(getattr(tpack, task_name))
return 'ok'
# 暂时假设无参(如果有参需要考虑序列化问题,一般python的数据需要pkl序列化)
@app.route('/tasks/<task_name>', methods=['GET', 'POST'])
def tasks(task_name):
print(task_name)
# 是否存在任务
is_task = hasattr(tpack, task_name)
print(is_task)
if is_task:
task_module = getattr(tpack, task_name)
print(task_module)
task_func = getattr(task_module, task_name)
return task_func()
else:
return 'no taskname'
if __name__ == '__main__':
# app.run(debug=True)
app.run()
task1.py
内容
def task1():
the_str = 'hello , i am task1 , modified 4 '
print(the_str)
return the_str
__init__.py
内容
from . import task1
task_pack的作用是把许多task整合到一起,一个task一个文件(模块)。
时刻1:调用task1,内容如下
时刻2:修改task1
def task1():
the_str = 'hello , i am task1 , modified 5 '
print(the_str)
return the_str
结果没有变化:
时刻3:请求热加载模块
时刻4:再次请求,返回重新加载(更改)过的结果。
另外,从增删改查(CRUD)的角度上,做如下修改:
# 好像只能按模块reload
@app.route('/reload_module/<task_name>',methods=['GET', 'POST'])
def reload_module(task_name):
if not hasattr(tpack,task_name):
reload(tpack)
else:
reload(getattr(tpack, task_name))
return 'ok'
@app.route('/remove_task/<task_name>', methods=['GET', 'POST'])
def remove_task(task_name):
if not hasattr(tpack, task_name):
return 'no such task'
else:
delattr(tpack, task_name)
return 'ok, remove' + task_name
reload_module
的修改使得新增task时(当前内存里加载的包没有这个属性),会对整个包进行加载(Create);原来的则是对已有包的修改(Update)。remove_task
是一种软删除(soft DELETE)的方法,它使得当前运行的内存中去掉了某个task; 如果要彻底删除(hard DELETE)的化就在包里的__init__.py
中去掉某个task的导入就可以了。
用途
- 1 在celery的任务框架中,动态修改任务
- 2 在启动服务的时候加载静态资源,通过热加载的方式改变静态资源