项目一开始就可能得关注两者有个非常大的设计差异,django会在自己的内部包装好所有的全局变量,用引擎之类的安装或者引入就行。但flask的app之类的各种插件由于都是一个一个的插件库,所以都得在项目中进行初始化,之后的全局化也得自己通过引用解决。
但是python中flask下这样子的多次调用,其中的依赖很容易发生问题,从而导致无法import一个项目文件,或者引入后,不具有你定义的所有属性。
flask web开发-基于python的web应用开发实战中也有提到,简单的flask开发中,一个蓝本的一般放在python初始化文件里__init__.py
from flask import Blueprint
main = Blueprint('main',__name__)
from . import views,errors
最后一句的from . import views
就是为了避免依赖的问题。
这个问题在Effective Python中也有提到,python引入模块时,会按照深度优先的顺序执行下列操作
- 在由sys.path所指定的路径中,搜寻引入模块
- 从该模块中加载代码,并保证这段代码能够正确编译
- 创建与该模块相对应的空对象
- 把这个空的模块对象,添加到sys.modules里面
- 运行模块对象中的代码,以定义其内容
大多数时候,如果你没有将import views放在最后一句而放在前面,由于views文本中使用了main,那么就会导致引入了一个空的main文件,main变量应该也不存在。
除了这种比较简单的问题,我遇到的问题的引入流程大概是。
- init app,db
- 引入views
- views
- 引入用于views的各种tools
- tools (包括但不局限于数据库的搜索)
- 引入数据库db
- db
这个时候大概就可以明白有什么问题了,第一步没有完成但是一直往深处执行就遇到了需要第一步正在初始化的对象,也就导致整个导入依赖出现问题。
避免这种依赖的方法有大概有三种
- 调整引入顺序
- 先引入方法,再在方法中配置,再运行
- 动态引入
不过由于flask的特殊性,重构代码基本不用考虑,引入是必须的,而且顺序在一个中大型项目里也很难调整。我现在临时使用的是,动态引入。将views与tools的引入关系包装在views 函数中,而不是引入到整个文件。但是由于import的开销也不小,导致整个项目可能运行起来会变的缓慢。
所以之后我优化时将工具们包装进一个工厂函数里同一调用也是十分有必要的。
另外app的位置,后来为了避免问题,我也是直接在项目外层创建了一个handle_init.py 去收纳app与db的初始化过程。