Tornado是什么
一个网络框架,同时也是一个异步网络库。其网络库适合长轮训和网络库。
源码下载
从这里 将源码进行下载,下载后切换到分支1.2,因为最小的版本,则意味着源码分析的难度降低。我们看看如何切换。
切换分支到1.2
可以看到现在我么那种本地分支master分支上。通过git branch -a 可以查看所有的分支信息,下面是切换版本 使用 git checkout 来切换。
目录结构
其中,tornado目录为该文件的核心目录,我们将demos里面中的helloworld.py代码,拿出来,进行debug。
hello world.py
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def main():
tornado.options.parse_command_line()
application = tornado.web.Application([
(r"/", MainHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
看上去很简单,就是当输入localhost:8888的时候,返回Hello, world。首先看一下,解析命令行参数。
parse_command_line函数
这里首先是解析命令行参数,设计得很精妙。
def parse_command_line(args=None):
"""Parses all options given on the command line.
We return all command line arguments that are not options as a list.
"""
# 默认情况下使用sys.argv列表,那么args至少有一个值,就是你脚本的名称。
if args is None: args = sys.argv
remaining = []
# 显然len(args)至少为1,如果为1,表示没有参数,xrange(1, len(args))
# 生成一个空对象。
for i in xrange(1, len(args)):
# All things after the last option are command line arguments
# 开始的参数如果没有以-开始,那么整个参数都有问题。
if not args[i].startswith("-"):
remaining = args[i:]
break
# 如果你的参数仅仅是--,后面没有跟参数,那么后面整个参数都有问题。
if args[i] == "--":
remaining = args[i+1:]
break
# 获取参数名称
arg = args[i].lstrip("-")
name, equals, value = arg.partition("=")
name = name.replace('-', '_')
# 如果name不在tornado支持的options中,表示不识别该选项或命令行参数
if not name in options:
print_help()
raise Error('Unrecognized command line option: %r' % name)
# 获取已经定义的选项值。
option = options[name]
# 等号为空字符串,那么表示该命令行参数可能是一个选项
if not equals:
#本身是一个选项,打开即可
if option.type == bool:
value = "true"
else:
# 否则,应该有值
raise Error('Option %r requires a value' % name)
option.parse(value)
# 如果是help命令,打印出help信息,退出即可
if options.help:
print_help()
sys.exit(0)
# Set up log level and pretty console logging by default
# 如果设置的是logging,那么设置logging level
if options.logging != 'none':
logging.getLogger().setLevel(getattr(logging, options.logging.upper()))
enable_pretty_logging()
return remaining
我们用如下代码进行测试:
#!/usr/bin/env/python
import tornado.options
from tornado.options import parse_command_line
def main():
"""
"""
args = ["file_name", "--help"]
parse_command_line(args)
if __name__== "__main__":
main()
options源码查看
在tornado中有一个已经定义的实例options,我们在parse_command_line中已经看到了,其已经定义了很多tornado支持的选项。我们看看其实例化和_Options类实现:
# options实例化,用的是_Options类的类方法。
options = _Options.instance()
class _Options(dict):
"""Our global program options, an dictionary with object-like access."""
@classmethod
def instance(cls):
if not hasattr(cls, "_instance"):
cls._instance = cls()
return cls._instance
def __getattr__(self, name):
# 如果值对象类型为_Option,那么就返回其值。
if isins