设为首页 加入收藏

TOP

Tornado源码分析之起步(二)
2017-09-30 16:59:28 】 浏览:381
Tags:Tornado 源码 分析 起步
tance(self.get(name), _Option): return self[name].value() raise AttributeError("Unrecognized option %r" % name)options = _Options.instance()

我们看看,_Options实际上是一个字典,其定义如上,使用了一个单例模式,注意到hasattr的使用,以及__getattr__魔法方法的使用。我们看看值类型_Option定义:


class _Option(object):
    def __init__(self, name, default=None, type=str, help=None, metavar=None,
                 multiple=False, file_name=None):
        if default is None and multiple:
            default = []
        self.name = name
        self.type = type
        self.help = help
        self.metavar = metavar
        self.multiple = multiple
        self.file_name = file_name
        self.default = default
        # 默认值为None
        self._value = None

_Option的parse方法

在parse_command_line中有一句option.parse(value),其根据将参数传入的值,设置option为该值。


def parse(self, value):
        # 注意这种字典方式
        # 其作用是根据参数的类型(比如:是一个简单的选项,或者其值应该为字符串)
        # 选择相应的解析函数。
        _parse = {
            # 
            datetime.datetime: self._parse_datetime,
            datetime.timedelta: self._parse_timedelta,
            bool: self._parse_bool,
            str: self._parse_string,
        }.get(self.type, self.type)
        # 值有多个
        if self.multiple:
            if self._value is None:
                self._value = []
            # 获取每个
            for part in value.split(","):
                if self.type in (int, long):
                    # allow ranges of the form X:Y (inclusive at both ends)
                    lo, _, hi = part.partition(":")
                    # 对于int, long type,_parse返回的是int()和long()方法,
                    # 很巧妙
                    lo = _parse(lo)
                    hi = _parse(hi) if hi else lo
                    # 设置添加多个系列值
                    self._value.extend(range(lo, hi+1))
                else:
                    self._value.append(_parse(part))
        else:
            self._value = _parse(value)
        return self.value()

_parse = { xxxx}.get(self.type, self.type)有点继承的味道,根据传入值的类型,来选择相应的解析方式。实现的比较优雅,值得学习。

define函数

我们知道tornado实际上在项目中,在options添加了几个默认的_Option对象。

define("help", type=bool, help="show this help information")
define("logging", default="info",
       help=("Set the Python log level. If 'none', tornado won't touch the "
             "logging configuration."),
       metavar="info|warning|error|none")
define("log_to_stderr", type=bool, default=None,
       help=("Send log output to stderr (colorized if possible). "
             "By default use stderr if --log_file_prefix is not set and "
             "no other logging is configured."))
define("log_file_prefix", type=str, default=None, metavar="PATH",
       help=("Path prefix for log files. "
             "Note that if you are running multiple tornado processes, "
             "log_file_prefix must be different for each of them (e.g. "
             "include the port number)"))
define("log_file_max_size", type=int, default=100 * 1000 * 1000,
       help="max size of log files before rollover")
define("log_file_num_backups", type=int, default=10,
       help="number of log files to keep")

具体实现:

  if name in options:
        # 重复定义不允许
        raise Error("Option %r already defined in %s", name,
                    options[name].file_name)
    frame = sys._getframe(0)
    # 用来获取当前文件名
    options_file = frame.f_code.co_filename
    file_name = frame.f_back.f_code.co_filename
    # 如果是在options.py使用了define这个函数,
    # 那么file_name就默认为空
    if file_name == options_file: file_name = ""
    options[name] = _Option(name, file_name=file_name, default=default,
                            type=type, help=help, metavar=metavar,
                            multiple=multiple)

sys._getframe(0)表示调用栈帧顶部,也就是define这个函数。下面的frame.f_code.co_filename表示定义define这个函数脚本名称(包含路径), 后面的fr

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇python是否需要每行以分号结束 下一篇python特殊方法定制类

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目