总结体会:
options这个文件是用来管理程序运行过程中配置的,它采用了单例模式,整个程序运行时只有一个实例存在。
参数可以从命令行读取,也可以从配置文件中读取,就看你怎么用了。
同时,options这个类也被tornado自己所用,存放了一些运行时的所需的参数(我只看了log.py文件,日志的一些参数的确用了options)。
实现原理:
options单例化的对象时OptionParser,OptionParser的组成:
1 一个名叫_options名称的字典对象,其中每个对象的内容都是_Option实例对象。
2 _parse_callbacks名称的列表对象,目前从定义上讲应该是回调函数的列表。
然后接着说_Option类,它实际是定义了一种数据对象格式,包括name,type,help,metavar,multiple,file_name,group_name,callback,default,_value,这些变量是作者认为在使用时可能需要定义的。
代码分段:
经过上面分析,我个人认为应该把options.py代码分为以下几段(除去了文件头import部分):
1 类OptionParser:options存储对象的类
2 类_Mockable:这其实是作者针对依赖库变化打的补丁,我们暂时不需要考虑
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class _Mockable(object): 2 """`mock.patch` compatible wrapper for `OptionParser`. 3 4 As of ``mock`` version 1.0.1, when an object uses ``__getattr__`` 5 hooks instead of ``__dict__``, ``patch.__exit__`` tries to delete 6 the attribute it set instead of setting a new one (assuming that 7 the object does not catpure ``__setattr__``, so the patch 8 created a new attribute in ``__dict__``). 9 10 _Mockable's getattr and setattr pass through to the underlying 11 OptionParser, and delattr undoes the effect of a previous setattr. 12 """ 13 def __init__(self, options): 14 # Modify __dict__ directly to bypass __setattr__ 15 self.__dict__['_options'] = options 16 self.__dict__['_originals'] = {} 17 18 def __getattr__(self, name): 19 return getattr(self._options, name) 20 21 def __setattr__(self, name, value): 22 assert name not in self._originals, "don't reuse mockable objects" 23 self._originals[name] = getattr(self._options, name) 24 setattr(self._options, name, value) 25 26 def __delattr__(self, name): 27 setattr(self._options, name, self._originals.pop(name))
3 类_Option:用于OptionParse的需求对象
4 options = OptionParser() :实例化OptionParse对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 options = OptionParser() 2 """Global options object. 3 4 All defined options are available as attributes on this object. 5 """
5 接口区:用于对配置对象options做操作,这里的诸多函数实际上是对options对象内部函数的一个封装。注意:实例化在这里有意义了,它们是对4步options对象直接做操作,而不是对类做操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def define(name, default=None, type=None, help=None, metavar=None, 2 multiple=False, group=None, callback=None): 3 """Defines an option in the global namespace. 4 5 See `OptionParser.define`. 6 """ 7 return options.define(name, default=default, type=type, help=help, 8 metavar=metavar, multiple=multiple, group=group, 9 callback=callback) 10 11 12 def parse_command_line(args=None, final=True): 13 """Parses global options from the command line. 14 15 See `OptionParser.parse_command_line`. 16 """ 17 return options.parse_command_line(args, final=final) 18 19 20 def parse_config_file(path, final=True): 21 """Parses global options from a config file. 22 23 See `OptionParser.parse_config_file`. 24 """ 25 return options.parse_config_file(path, final=final) 26 27 28 def print_help(file=None): 29 """Prints all the command line options to stderr (or another file). 30 31 See `OptionParser.print_help`. 32 """ 33 return options.print_help(file) 34 35 36 def add_parse_callback(callback): 37 """Adds a parse callback, to be invoked when option parsing is done. 38 39 See `OptionParser.add_parse_callback` 40 """ 41 options.add_parse_callback(callback)
6 调用函数define_logging_options(options):这里就是tornado自己的默认运行参数了,主要是日志。指向log.py里面的一些预先设置好的配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # Default options 2 define_logging_options(options)
我们跳到log.py看函数是怎么写的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def define_logging_options(options=None): 2 """Add logging-related flags to ``options``. 3 4 These options are present automatically on the default options instance; 5 this method is only necessary if you have created your own `.OptionParser`. 6 7 .. versionadded:: 4.2 8 This function existed in prior versions but was broken and undocumented until 4.2. 9 """ 10 if options is None: 11 # late import to prevent cycle 12 import tornado.options 13 options = tornado.options.options 14 options.define("logging", default="info", 15 help=("Set the Python log level. If 'none', tornado won't touch the " 16 "logging configuration."), 17 metavar="debug|info|warning|error|none") 18 options.define("log_to_stderr", type=bool, default=None, 19 help=("Send log output to stderr (colorized if possible). " 20 "By default use stderr if --log_file_prefix is not set and " 21 "no other logging is configured.")) 22 options.define("log_file_prefix", type=str, default=None, metavar="PATH", 23 help=("Path prefix for log files. " 24 "Note that if you are running multiple tornado processes, " 25 "log_file_prefix must be different for each of them (e.g. " 26 "include the port number)")) 27 options.define("log_file_max_size", type=int, default=100 * 1000 * 1000, 28 help="max size of log files before rollover") 29 options.define("log_file_num_backups", type=int, default=10, 30 help="number of log files to keep") 31 32 options.define("log_rotate_when", type=str, default='midnight', 33 help=("specify the type of TimedRotatingFileHandler interval " 34 "other options:('S', 'M', 'H', 'D', 'W0'-'W6')")) 35 options.define("log_rotate_interval", type=int, default=1, 36 help="The interval value of timed rotating") 37 38 options.define("log_rotate_mode", type=str, default='size', 39 help="The mode of rotating files(time or size)") 40 41 options.add_parse_callback(lambda: enable_pretty_logging(options))
类OptionParser和类_Option我将在下一步单独说明
本文部分内容借鉴了: