源码看Flask框架配置管理(3)

在settings.py模块中,我们定义了多个类,首先是Config类,这个类定义的是默认配置,其他类都继承Config类,每一个之类代表一种配置,如果需要子类中可以覆写Config,如果不覆写则使用Config中的默认配置。怎么使用呢?

from flask import Flask import settings app = Flask(__name__) app.config.from_object(settings.ProductionConfig) print('DEBUG:', app.config.get('DEBUG')) print('TESTING:', app.config.get('TESTING')) print('DATABASE_URI:', app.config.get('DATABASE_URI'))

输出:

DEBUG: False

TESTING: False

DATABASE_URI: mysql://user@localhost/foo

使用这种方法的好处是可以充分利用面向对象中继承等的优良特性共享配置,设置多套配置,使用时,只需要针对实际需要修改app.config.from_object(settings.ProductionConfig)中传入的类即可。这种方法在实际开发中也是使用最多的。

5 配置方式3-py文件:from_pyfile

继续解析源码:

def from_pyfile(self, filename, silent=False): filename = os.path.join(self.root_path, filename) # 拼接路径 d = types.ModuleType("config") # 创建一个模块对象 d.__file__ = filename try: with open(filename, mode="rb") as config_file: #将文件内容解析到d exec(compile(config_file.read(), filename, "exec"), d.__dict__) except IOError as e: if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): return False e.strerror = "Unable to load configuration file (%s)" % e.strerror raise self.from_object(d) # 调用上面说到过的from_object()方法 return True

在上一章节分析from_object()方法时,我们说到,from_object()方法可以接受一个模块作为参数,from_pyfile()方法接受的就是一个py文件作为参数,在Python中一个py文件就是一个模块,那from_object()方法与from_pyfile()方法有什么区别呢?从源码汇总我们可以看出,from_pyfile()方法接受一个文件名作为参数,我们可以认为,使用from_pyfile()方法读取配置时,我们只能直接将配置写在py文件中,而不能是写在py文件中定义的类。from_pyfile()方法思路就是传入一个py文件名,然后对文件进行解析,转为模块对象,调用from_object()方法对解析到的模块对象读取配置。

分析完了我们就来使用一下吧,settings.py文件内容如下:

DEBUG = True TESTING = True A = 123

读取配置:

from flask import Flask app = Flask(__name__) app.config.from_pyfile('settings.py') print('DEBUG:', app.config.get('DEBUG')) print('TESTING:', app.config.get('TESTING')) print('A:', app.config.get('A'))

输出:

DEBUG: True

TESTING: True

A: 123

6 配置方式4-字典元组:from_mapping

这种方式是以元组或者字典的形式来管理配置,先来看看源码:

def from_mapping(self, *mapping, **kwargs): mappings = [] # 用于存放待会儿解析出来的数据 if len(mapping) == 1: # 只能接受一个位置参数 if hasattr(mapping[0], "items"): # 如果是字典 mappings.append(mapping[0].items()) # 以(key, value)的形式放到mappings列表中 else: mappings.append(mapping[0]) # 如果不是字典,直接放到mappings列表中 elif len(mapping) > 1: # 如果位置参数数量多于1个就会抛出异常 raise TypeError( "expected at most 1 positional argument, got %d" % len(mapping) ) mappings.append(kwargs.items()) # 对于关键字参数,则直接以(key, vlaue)形式放到mappings列表中 for mapping in mappings: for (key, value) in mapping: if key.isupper(): # 如果key是大写的,才会修改配置 self[key] = value return True

就算看完了上面的代码解析,你也许知道了代码做了什么,但是却还不知道为什么这么做,来,我们尝试使用一下也许你就明白了:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9d8d5bd5e5492a644daa78646057f54b.html