search
HomeBackend DevelopmentPython TutorialIntroduction and usage examples of tarnado
Introduction and usage examples of tarnadoJun 30, 2017 pm 02:26 PM
Source codeseries

Directory

  • tarnado

  • ##tarnado source code installation

  • tarnado test program

  • # #Application class analysis

1. Introduction to tarnado

Recently I was learning Python and came into contact with tarnado accidentally. , I feel that tarnado is pretty good, so what exactly is tarnado? tarnado is a non-blocking web server framework developed in Python. It is very different from many mainstream web frameworks (of course I really don’t know much about other web frameworks). The epoll and non-blocking methods allow it to Thousands of connections per second, ideal for real-time web services. The following address is the official explanation of tarnado

2. Tarnado source code installation

Go to the above address to download tornado-1.2.1.tar.gz

After decompressing it, go to cmd Find this path in the command box and install it. The specific steps are as follows:

Note: After testing by myself, this code cannot be executed on python3.5 , it can be executed on 2.7, so it is recommended to install it on python2.7 for testing and learning. 3. Test program

After the installation is complete, open pycharm, create a new py file, and write the following test code. After execution, enter http in the browser: //127.0.0.1:8888 will display the words hello and world, which means the installation is successful.

 1 import tornado.ioloop 2 import tornado.web 3  4 class MainHandler(tornado.web.RequestHandler): 5     def get(self): 6         self.write("Hello, world") 7  8 application = tornado.web.Application([ 9     (r"/", MainHandler),10 ])11 12 if __name__ == "__main__":13     application.listen(8888)14     tornado.ioloop.IOLoop.instance().start()
Test code

4. Analysis of application class

Now we are finally going to parse the application, but before parsing, let’s talk about the execution process of the test code.

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # zhou 4 # 2017/6/27 5  6 # 导入两个模块 7 import tornado.ioloop 8 import tornado.web 9 10 # 1. 把类RequestHandler载入到内存中11 # 2. 把类RequestHandler做为参数传入MainHandler中12 # 3. 把类MainHandler载入到内存中13 # 以上三个步骤实质上都不会坐任何操作,仅仅只是把类装载到内存中以便后续调用14 class MainHandler(tornado.web.RequestHandler):15     def get(self):16         self.write("Hello, world")17 18 19 # 丛这一步骤开始才开始真正的创建对象20 # 1. 类Application创建了一个对象,名称为application21 # 2. r"/" 这个是正则表达式类型的/,也就是我们在浏览器中输入的url22 # 3. 把类MainHandler作为参数传递到application中23 # 4. 这里面传递的仅仅只是一个变量[]24 application = tornado.web.Application([25     (r"/", MainHandler),26 ])27 28 if __name__ == "__main__":29     30     # 调用application对象中的listen方法,把8888作为端口号传递进去31     application.listen(8888)32     tornado.ioloop.IOLoop.instance().start()
Introduction to the test program execution process
The first thing to analyze is the following line of code

application =
A collection of request handlers that make up a web application.把许多请求处理器组合起来以实现web应用
<br>
 1. Application initialization process

 1 def __init__(self, handlers=None, default_host="", transforms=None, 2              wsgi=False, **settings): 3     if transforms is None: 4         self.transforms = [] 5         if settings.get("gzip"): 6             self.transforms.append(GZipContentEncoding) 7         self.transforms.append(ChunkedTransferEncoding) 8     else: 9         self.transforms = transforms10     self.handlers = []11     self.named_handlers = {}12     self.default_host = default_host13     self.settings = settings14     self.ui_modules = {}15     self.ui_methods = {}16     self._wsgi = wsgi17     self._load_ui_modules(settings.get("ui_modules", {}))18     self._load_ui_methods(settings.get("ui_methods", {}))19     if self.settings.get("static_path"):20         path = self.settings["static_path"]21         handlers = list(handlers or [])22         static_url_prefix = settings.get("static_url_prefix",23                                          "/static/")24         handlers = [25                        (re.escape(static_url_prefix) + r"(.*)", StaticFileHandler,26                         dict(path=path)),27                        (r"/(favicon\.ico)", StaticFileHandler, dict(path=path)),28                        (r"/(robots\.txt)", StaticFileHandler, dict(path=path)),29                    ] + handlers30     if handlers: self.add_handlers(".*$", handlers)31 32     # Automatically reload modified modules33     if self.settings.get("debug") and not wsgi:34         import autoreload35         autoreload.start()
Initialization code
Code一

  . It encapsulates tranforms variables for the object application,

  . If the user does not specify the variables, the system defaults to one between the server and the client. During the transmission process, it must be compressed to a certain extent and transmitted piece by piece

###################################################if transforms is None:
    self.transforms = []if settings.get("gzip"):
        self.transforms.append(GZipContentEncoding)
    self.transforms.append(ChunkedTransferEncoding)else:
    self.transforms = transforms###################################################这里面主要包含了三个类:
    GZipContentEncoding(OutputTransform)        # gzip内容编码ChunkedTransferEncoding(OutputTransform)    # 分块传输编码OutputTransform()                           # 是上面两个类的父类        解释:A transform modifies the result of an HTTP request(e.g., GZip encoding)
        主要是用来对一个http请求的结果进行转换的,可以是gzip压缩

 Code 2

  . It encapsulates a series of variables for the object application. The two variables ui_modules and ui_methods are not understood yet, and will be supplemented later.

self.handlers = []
self.named_handlers = {}
self.default_host = default_host
self.settings = settings
self.ui_modules = {}
self.ui_methods = {}
self._wsgi = wsgi

Code 3

What is the difference between methods? I think it should be the modules and methods defined by yourself and those provided by the system by default.

self._load_ui_modules(settings.get("ui_modules", {}))
self._load_ui_methods(settings.get("ui_methods", {}))

  他主要调用了两个方法,在此仅仅对第一个方法进行简单的描述(_load_ui_modules)

  因为第二个方法和这个modules是一样的

 1 def _load_ui_modules(self, modules): 2     if type(modules) is types.ModuleType: 3         self._load_ui_modules(dict((n, getattr(modules, n)) 4                                    for n in dir(modules))) 5     elif isinstance(modules, list): 6         for m in modules: self._load_ui_modules(m) 7     else: 8         assert isinstance(modules, dict) 9         for name, cls in modules.iteritems():10             try:11                 if issubclass(cls, UIModule):12                     self.ui_modules[name] = cls13             except TypeError:14                 pass
_load_ui_modules源代码

  对于上面源代码解析

# 把传入的模块modules全部变成字典的形式封装到ui_modules变量中def _load_ui_modules(self, modules):# types是一个.py文件,他主要是为了定义一些简单的函数,类似于内置函数可以直接拿来使用的# types里面关于ModuleType的描述是:ModuleType = type(sys) 也就是sys的类型<type># 这里其实就是为了判断传出的modules是不是一个模块的类型,如果是就把它变成一个字典形式递归判断if type(modules) is types.ModuleType:
        self._load_ui_modules(dict((n, getattr(modules, n))                                   for n in dir(modules)))#判断modules是不是一个列表,如果是列表,就把列表里面的元素重新代入方法中进行调用                             elif isinstance(modules, list):for m in modules: self._load_ui_modules(m)else:# 此处是一个断言机制,也就是说已经肯定了modules一定是一个字典形式的样子assert isinstance(modules, dict)# 因为modules是一个字典,所以就把键和值分别赋值给name和cls,然后判断每一个键的值cls是不是UIModule的一个子类,如果是# 就把这个值添加到前面封装的一个变量中self.ui_modules[name] = clsfor name, cls in modules.iteritems():try:if issubclass(cls, UIModule):
                    self.ui_modules[name] = clsexcept TypeError:pass</type>

 

  代码四

   . 它定义了一系列的变量,最重要的变量是handler,  其中又引出了一个类StaticFileHandler而这个类又是继承了RequestHandler,因为此处并没有创建任何关于这个类的对象,所以此处不再深究等真正调用时候在来关注。

   但是从条件语句中,我们就可以看出来,当setting中不含static的时候,并不会去创建这些变量,这一点是要注意的。

# 定义了一系列的变量如handlers,path,static_url_prefix   # 当settings中包含了static_path这个键的时候,才会去定义这些变量         if self.settings.get("static_path"):
    path = self.settings["static_path"]
    handlers = list(handlers or [])
    static_url_prefix = settings.get("static_url_prefix",                                     "/static/")
    handlers = [
        (re.escape(static_url_prefix) + r"(.*)", StaticFileHandler,
         dict(path=path)),
        (r"/(favicon\.ico)", StaticFileHandler, dict(path=path)),
        (r"/(robots\.txt)", StaticFileHandler, dict(path=path)),
    ] + handlers

 

  代码五

    . 添加给定的处理器到系统的处理器列表中。(其实这样说可能不太准确, 因为我们从代码四就可以看出来,如果我们给定的url包含了static_path,那么给定的处理器无论如何都会发生改变)

if handlers: self.add_handlers(".*$", handlers)

  代码六  

    add_handles函数的解析

def add_handlers(self, host_pattern, host_handlers):# 添加给定的处理器到系统的处理器列表中,注意主机模式是按顺序进行处理的,直到第一个被匹配到的这就意味着所有给定主机的处理器必须被添加到处理器中"""Appends the given handlers to our handler list.

    Note that host patterns are processed sequentially in the
    order they were added, and only the first matching pattern is
    used.  This means that all handlers for a given host must be
    added in a single add_handlers call."""# 如果给定主机模式不是以"$"结尾的,就添加$到结尾if not host_pattern.endswith("$"):
        host_pattern += "$"handlers = []# The handlers with the wildcard host_pattern are a special# case - they're added in the constructor but should have lower# precedence than the more-precise handlers added later.# If a wildcard handler group exists, it should always be last# in the list, so insert new groups just before it.# 带有通配符的handlers是一个特殊情况,他们本来在构造方法就已经被添加了,但是他们的优先级却低于一些重要的处理器,因此应该在之后被添加# 所以如果带有通配符的处理器组存在,就应该把他们放在一个列表的最后面,否则就插在他的前面# 下面这段代码就是这个意思,如果他的pattern是'.*$'开头的,代表他是没有通配符的,所以就把他插入最后一个的前面,否则有通配符的就直接添加到后面if self.handlers and self.handlers[-1][0].pattern == '.*$':
        self.handlers.insert(-1, (re.compile(host_pattern), handlers))else:
        self.handlers.append((re.compile(host_pattern), handlers))# 这个是对我们传入的host_handlers进行一个解析,把第一个采纳数给pattern,第二个给handler如果有三个,就赋值给kwargs如果没有第三个kwargs=={}for spec in host_handlers:if type(spec) is type(()):assert len(spec) in (2, 3)
            pattern = spec[0]
            handler = spec[1]if len(spec) == 3:
                kwargs = spec[2]else:
                kwargs = {}# 赋值完成之后就把这些参数封装到类URLSpec中spec = URLSpec(pattern, handler, kwargs)# 类URLSpec创建了对象spec之后,会重新给self.named_handlers添加一个handlers的键值对,如果键值本身就存在,就会往日志里面写入警告信息        handlers.append(spec)if spec.name:if spec.name in self.named_handlers:
                logging.warning("Multiple handlers named %s; replacing previous value",
                    spec.name)
            self.named_handlers[spec.name] = spec

 

  

  代码七

  类URLSpec的解析

  在代码六中创建了一个spec对象,用的类URLSpec创建的

class URLSpec(object):# 这个类的作用主要是在url和handlers之间做一个特定的映射,主要的体现应该就是前面的变量name_handlers# 前面的赋值语句:self.named_handlers[spec.name] = spec"""Specifies mappings between URLs and handlers."""def __init__(self, pattern, handler_class, kwargs={}, name=None):"""Creates a URLSpec.

        Parameters:
        # 传递进来得主机模式
        pattern: Regular expression to be matched.  Any groups in the regex
            will be passed in to the handler's get/post/etc methods as
            arguments.
            
        # 这个不是特别懂,但是意思是RequestHandler的子类将被调用
        handler_class: RequestHandler subclass to be invoked.
        kwargs (optional): A dictionary of additional arguments to be passed
            to the handler's constructor.
            
        # 这个handler的名字,是一个额外的参数
        name (optional): A name for this handler.  Used by
            Application.reverse_url."""if not pattern.endswith('$'):
            pattern += '$'self.regex = re.compile(pattern)
        self.handler_class = handler_class
        self.kwargs = kwargs
        self.name = name
        self._path, self._group_count = self._find_groups()

  代码八

  方法self._find_groups() 

  这个方法比较有意思,后面会带一个例子来解释一下

def _find_groups(self):# 就是给特定的url返回一个元组,下面的就是例子,括号里面的内容都会转换成%s,后面的2代表小括号括号的个数"""Returns a tuple (reverse string, group count) for a url.

    For example: Given the url pattern /([0-9]{4})/([a-z-]+)/, this method
    would return ('/%s/%s/', 2)."""# 得到pattern的字符串形式,去掉开头的^和结尾的$符号pattern = self.regex.patternif pattern.startswith('^'):
        pattern = pattern[1:]if pattern.endswith('$'):
        pattern = pattern[:-1]# 如果正常情况下regex.groups的值应该是等于count的,除非特别复杂的url,会返回两个noneif self.regex.groups != pattern.count('('):# The pattern is too complicated for our simplistic matching,# so we can't support reversing it.return (None, None)        # 这个就是把url转换成元组的具体代码,代码实现的是把括号里面的内容全部转换成%spieces = []for fragment in pattern.split('('):if ')' in fragment:
            paren_loc = fragment.index(')')if paren_loc >= 0:
                pieces.append('%s' + fragment[paren_loc + 1:])else:
            pieces.append(fragment)    # 把picese重新拼接成字符,返回回去return (''.join(pieces), self.regex.groups)
import re

pattern = "/abcd123([0-9]{4})/lwjeg([a-z-]+)/"regex = re.compile(pattern)
pieces = []print(pattern.split('('))for fragment in pattern.split('('):if ')' in fragment:# 找到‘)’的位置paren_loc = fragment.index(')')if paren_loc >= 0:# 把')'之后的所有内容拼接起来pieces.append('%s' + fragment[paren_loc + 1:])else:
        pieces.append(fragment)print(pieces)

结果:
['/abcd123', '[0-9]{4})/lwjeg', '[a-z-]+)/']
['/abcd123', '%s/lwjeg', '%s/']

   代码九 

# 自动的去重载改变的模块,这个调用的是autorelaad模块实现的    # Automatically reload modified modulesif self.settings.get("debug") and not wsgi:import autoreload
    autoreload.start()

  至此 

application = tornado.web.Application([<br>    (r"/", MainHandler),<br>])

The above is the detailed content of Introduction and usage examples of tarnado. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python在软件源码保护中的应用实践Python在软件源码保护中的应用实践Jun 29, 2023 am 11:20 AM

Python语言作为一种高级编程语言,具有简单易学、易读易写等特点,在软件开发领域中得到了广泛的应用。然而,由于Python的开源特性,源代码很容易被他人轻易获取,这就给软件源码保护带来了一些挑战。因此,在实际应用中,我们常常需要采取一些方法来保护Python源代码,确保其安全性。在软件源码保护中,有多种针对Python的应用实践可供选择。下面将介绍几种常见

小米 15 系列全代号曝光:Dada、Haotian、Xuanyuan小米 15 系列全代号曝光:Dada、Haotian、XuanyuanAug 22, 2024 pm 06:47 PM

小米15系列预计将于10月份正式发布,其全系列代号已在外媒MiCode代码库中曝光。其中,旗舰级小米15Ultra代号为"Xuanyuan"(意为"轩辕"),此名源自中国神话中的黄帝,象征着尊贵。小米15的代号为"Dada",而小米15Pro则以"Haotian"(意为"昊天")为名。小米15SPro内部代号为"dijun",暗指《山海经》创世神帝俊。小米15Ultra系列涵盖

华为 Mate 60 系列最佳入手时机,新增 AI 消除 + 影像升级,更可享秋日礼遇活动华为 Mate 60 系列最佳入手时机,新增 AI 消除 + 影像升级,更可享秋日礼遇活动Aug 29, 2024 pm 03:33 PM

自去年华为Mate60系列开售以来,我个人就一直将Mate60Pro作为主力机使用。在将近一年的时间里,华为Mate60Pro经过多次OTA升级,综合体验有了显著提升,给人一种常用常新的感觉。比如近期,华为Mate60系列就再度迎来了影像功能的重磅升级。首先是新增AI消除功能,可以智能消除路人、杂物并对空白部分进行自动补充;其次是主摄色准、长焦清晰度均有明显升级。考虑到现在是开学季,华为Mate60系列还推出了秋日礼遇活动:购机可享至高800元优惠,入手价低至4999元。常用常新的产品力加上超值

idea如何查看tomcat的源码idea如何查看tomcat的源码Jan 25, 2024 pm 02:01 PM

idea查看tomcat源码的步骤:1、下载Tomcat源代码;2、在IDEA中导入Tomcat源代码;3、查看Tomcat源代码;4、理解Tomcat的工作原理;5、注意事项;6、持续学习和更新;7、使用工具和插件;8、参与社区和贡献。详细介绍:1、下载Tomcat源代码,可以从Apache Tomcat的官方网站上下载源代码包,通常这些源代码包是以ZIP或TAR格式等等。

iPhone 15 和iPhone 15 Pro 怎么挑?九大差异一次过目iPhone 15 和iPhone 15 Pro 怎么挑?九大差异一次过目Sep 14, 2023 am 08:01 AM

iPhone15与iPhone15Pro在今日正式发表,不过Pro系列作为高端机型,除了价格更高以外,也有许多专属功能,消费者在购买前得先认清差异,才不会在买了iPhone15后,才发现有些功能只有Pro系列才能用。显示器尽管搭载了相同的显示面板,但ProMotion自动适应更新频率技术与永远显示功能仍然是Pro系列专属。其余无论是在解析度、对比度、峰值亮度等层面,iPhone15与iPhone15Pro系列皆相同。动作按钮动作按钮目前是iPhone15Pro系列的专属设计,可以让使用者个人化自

PHP代码在浏览器中如何显示源码而不被解释执行?PHP代码在浏览器中如何显示源码而不被解释执行?Mar 11, 2024 am 10:54 AM

PHP代码在浏览器中如何显示源码而不被解释执行?PHP是一种服务器端脚本语言,通常用于开发动态网页。当PHP文件在服务器上被请求时,服务器会解释执行其中的PHP代码,并将最终的HTML内容发送到浏览器以供显示。然而,有时我们希望在浏览器中直接展示PHP文件的源代码,而不是被执行。本文将介绍如何在浏览器中显示PHP代码的源码,而不被解释执行。在PHP中,可以使

vue能显示源码吗vue能显示源码吗Jan 05, 2023 pm 03:17 PM

vue能显示源码,vue查看看源码的方法是:1、通过“git clone https://github.com/vuejs/vue.git”获取vue;2、通过“npm i”安装依赖;3、通过“npm i -g rollup”安装rollup;4、修改dev脚本;5、调试源码即可。

网站在线看源码网站在线看源码Jan 10, 2024 pm 03:31 PM

可以使用浏览器的开发者工具来查看网站的源代码,在Google Chrome浏览器中:1、打开 Chrome 浏览器,访问要查看源代码的网站;2、右键单击网页上的任何位置,然后选择“检查”或按下快捷键 Ctrl + Shift + I打开开发者工具;3、在开发者工具的顶部菜单栏中,选择“Elements”选项卡;4、看到网站的 HTML 和 CSS 代码即可。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software