Inside Flask - flask 扩展加载过程

flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask.ext.<扩展名> 来导入扩展包。一般使用方法见 flask 扩展。在最新的 0.11.1 代码中,不建议使用 flask.ext 加载扩展,可通过 flask_xxx 的名字直接调用扩展,那样就不需要 flask 自带的扩展机制,但了解一下原来的扩展实现机制还是很有意思的。

flask 在处理这些扩展的代码在 flask/extflask/exthook.py 中。

在 ext 包的 __init__.py 中,定义了一个 setup 函数 ::

def setup():
from ..exthook import ExtensionImporter
importer = ExtensionImporter(['flask_%s', 'flaskext.%s'], __name__)
importer.install()

然后就执行 setup 函数,并删除 setup 函数。setup 函数创建一个 flask.exhook.ExtensionImporter ,这个对象是真正执行扩展包导入的地方。

ExtensionImporter使用到 python 本身的模块搜索机制。我们知道 sys.path 是 python 的模块搜索路径,使用 import 导入模块时从 sys.path 列表中逐个查找。而 sys.meta_path 从字面看是元路径,在搜索时优先于 sys.path (或者默认的隐式模块加载器)。meta_path 里面定义其实不是路径,而是模块搜索类 finder 的列表。finder 包含 find_loaderfind_module 方法,用于查找对应模块加载器 loader,最后调用 loader 提供的 load_module 方法加载模块(注册到 sys.modules)。

ExtensionImporter 既是 finder 同时也是 loader。setup 函数在初始化ExtensionImporter 时,传入了一个扩展包名模式列表和当前模块的名字(flask.ext)。 flask.ext 在这里是作为一个包装器模块(必须条件), importer 把扩展模块挂在这个模块的名字之下。['flask_%s', 'flaskext.%s'] 则是搜索实际模块名时用的字符串模板,如 flask.ext.sqlalchemy 则会转换为真实模块名 flask_sqlalchemyflaskext.sqlalchemy ,并尝试 import (在下文中分析)。

首先,setup 函数调用 importer 的 install 方法,让 importer 把自己注册到 sys.meta_path 中成为一个 finder ::

def install(self):
sys.meta_path[:] = [x for x in sys.meta_path if self != x] + [self]

那么,当代码中调用 from flask.ext.sqlalchemy import xxx 时,ExtensionImporter 的 find_module 函数被调用,并返回自身作为 loader ::

def find_module(self, fullname, path=None):
if fullname.startswith(self.prefix) and \
fullname != 'flask.ext.ExtDeprecationWarning':
return self

然后,按照模块导入的流程,load_module 函数被调用。

def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
...

fullname 是模块全名 flask.ext.sqlalchemy。在加载模块时,先从 sys.modules 查看是否已加载,如果未有加载,那么将 fullname 去掉 flask.ext前缀,并转换为真实的模块名 ::

# 去掉前缀
modname = fullname.split('.', self.prefix_cutoff)[self.prefix_cutoff]
...
# 尝试加载真实模块
for path in self.module_choices:
realname = path % modname
try:
__import__(realname)
...
# 更新 sys.modules
module = sys.modules[fullname] = sys.modules[realname]
...
return module

至此,整个扩展模块的加载过程成功完成。

Inside Flask - flask 扩展加载过程的更多相关文章

  1. [转]PHP的执行流程,PHP扩展加载过程

    原文:http://www.imsiren.com/archives/535 为了以后能开发PHP扩展..就一定要了解PHP的执行顺序..这篇文章就是为C开发PHP扩展做铺垫. web环境 我们假设为 ...

  2. Dubbo源码解析之SPI(一):扩展类的加载过程

    Dubbo是一款开源的.高性能且轻量级的Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用.智能容错和负载均衡,以及服务自动注册和发现. Dubbo最早是阿里公司内部的RPC框架,于 ...

  3. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

  4. ThinkPHP3.2 加载过程(四)

    前言: 由于比较懒散,但是又是有点强迫症,所以还是想继续把ThinkPHP3.2的加载过程这个烂尾楼补充完整. ========================================分割线= ...

  5. Orchard 源码探索(Module,Theme,Core扩展加载概述)

    参考: http://www.orchardch.com/Blog/20120830071458 1. host.Initialize(); private static IOrchardHost H ...

  6. Orchard Module,Theme,Core扩展加载概述

    Orchard 源码探索(Module,Theme,Core扩展加载概述) 参考: http://www.orchardch.com/Blog/20120830071458 1. host.Initi ...

  7. Spring IOC bean加载过程

    首先我们不要在学习Spring的开始产生畏难情绪.Spring没有臆想的那么高深,相反,它帮我们再项目开发中制定项目框架,简化项目开发.它的主要功能是将项目开发中繁琐的过程流程化,模式化,使用户仅在固 ...

  8. (转)JVM类生命周期概述:加载时机与加载过程

    原文地址: http://blog.csdn.net/justloveyou_/article/details/72466105 JVM类加载机制主要包括两个问题:类加载的时机与步骤 和 类加载的方式 ...

  9. jvm(1)类加载(一)(加载过程,双亲加载)

    JVM类加载器机制与类加载过程 jvm虚拟机的种类: Hotspot(Oracle)(基本上都是在说这个) J9, JikesRVM(IBM) Zulu, Zing (Azul) Launcher是一 ...

随机推荐

  1. PHP 将秒数转换成时分秒

    将秒数转换成时分秒,PHP提供了一个函数gmstrftime,不过该函数仅限于24小时内的秒数转换.对于超过24小时的秒数,我们应该怎么让其显示出来呢,例如 34:02:02 $seconds = 3 ...

  2. 笔记本做wifi热点

    你可以开启windows 7的隐藏功能:虚拟WiFi和SoftAP(即虚拟无线AP),就可以让电脑变成无线路由器,实现共享上网.点开始 所有程序 命令提示符右键管理员身份运行命令提示符 运行命令:ne ...

  3. 移动端:active,:hover无法很好触发动画的解决方案

    移动端:active,:hover无法很好触发动画的解决方案 1:问题环境: 用css3定义了一个动画,使用:hover伪类调用动画时在移动端不能很好的进行动画. 2:解决方案: 定义一个open类, ...

  4. js两个小技巧【看到了就记录一下】

    1.不声明第三个变量实现交换 ,b=; a=[b,b=a][];//执行完这句代码之后 a的值为2 b的值为1了 2.&&和||的用法 (学会了立马感觉高大尚了吧) ; //传统if语 ...

  5. ACM Greedy Mouse

    Greedy Mouse 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 A fat mouse prepared M pounds of cat food,read ...

  6. ACM: FZU 2148 Moon Game - 海伦公式

     FZU 2148  Moon Game Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

  7. 【BZOJ】2172: Mario填格子

    题意 \(3 * 3\)的网格,给出左上角的数字\(m\)和右下角的数字\(m\),如果当前格子有数字\(x\),格子左边有个数字\(y\),格子上面有个数字\(z\),则\(y|x, z|x\).格 ...

  8. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  9. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  10. 实现UITableView循环利用

    tableViewUITableView循环利用 前言 大家都知道UITableView,最经典在于循环利用,这里我自己模仿UITableView循环利用,写了一套自己的TableView实现方案,希 ...