1. 引子
1. Django的settings配置文件中的中间件编写方式如下所示
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
2. 我们可以将其看作是列表中包含了多个字符串,但是字符串的作用其实类似于模块,如下示例
from django.middleware.security import SecurityMiddleware
3. 如果我们也想实现将一个个模块变成字符串的导入形式,就需要使用到一个叫做 'importlib' 的模块
2. importlib 模块
该模块可以通过字符串的形式导入模块
常规导入方式
from b import c
结果如下图所示,打印模块的结果是:
<module 'b.c' from 'F:\\python project\\pythonProject_importlib\\b\\c.py'>
字符串导入方式
import importlib
# 创建字符串
module_path = 'b.c'
# 以字符串形式导入
res = importlib.import_module(module_path)
print(res)
结果如下图所示,打印的结果和普通导入的一致
俩者区别
1. 普通导入方式可以导入文件中指定的对象,如下所示
from b.c import name
print(name)
2. 而字符串的方式最小导入单位是模块文件级别,如下示例的情况会报错
import importlib
module_path = 'b.c.name'
res = importlib.import_module(module_path)
print(name)
3. 功能的插拔式设计
用打印信息功能作为案例来比较,首先先使用普通函数的形式。
普通编写方式
在这种情况下,将功能封装到函数里,若是不想某单个函数执行直接在总函数里删除即可。
封装成配置
类似于settings文件的格式,封装成配置
1. 首先创建一个包,在包中创建多个py文件,每个py文件中均有一个类,类中均定义了send方法,使其符合多态性,例如
class QQ(object):
def __init__(self):
pass
# 定义send方法
def send(self, info):
print('qq', info)
2. 在settings.py文件中创建列表用于存放字符串路径,用点的方式指向最终的类,如下示例
NOTIFY_FUNC_LIST = [
'notify.qq.QQ',
'notify.weibo.WeiBo',
'notify.weixin.WeiXin',
]
3. 在notify包中的双下init文件中编写表示全部send方法的函数,如下示例
# 导入settings文件用于获取路径字符串
import settings
# 使用字符串形式导入,需要导入importlib
import importlib
# 创建send的总函数
def send_all(info):
# 循环获取配置文件中的字符串,格式为 'notify.qq.QQ'
for str_path in settings.NOTIFY_FUNC_LIST:
# 从右边开始切割字符串路径,并设定最大切割次数为1,切割完结果类似于 ['notify.qq', 'QQ']
module_str_path, class_str_name = str_path.rsplit('.', maxsplit=1)
# 导入切割后的字符串路径,类似于 notify.qq
module = importlib.import_module(module_str_path)
# 使用反射方法,获取模块中的类,getattr(x, 'y') 等价于 x.y
class_name = getattr(module, class_str_name)
# 实例化模块中的类
obj = class_name()
# 调用发送信息的功能,由于发送消息的方法都叫做send,所以均可以被调用
obj.send(info)
4. 然后还要在start.py文件中执行包中的函数,如下示例
# 需要先导入包,相当于导入了包中的__init__.py文件
import notify
if __name__ == '__main__':
# 执行发送消息的总方法
notify.send_all('你好啊')
5. 以上的步骤结束后,会执行所有在settings文件中配置好的路径中的方法,需要注意的是多态性。如果不想执行某个py
文件中的类方法时,只要在配置文件settings中删除该路径即可,这里只表达编写思想,可以使用别的案例替换。