百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

01.Tornado简介(tornadoweb)

ccwgpt 2024-10-14 08:42 21 浏览 0 评论

01.Tornado简介

Tornado是一个Python web框架和异步网络库,最初由FriendFeed开发。通过使用非阻塞网络I/O,Tornado可以扩展到数万个开放连接,使其成为长轮询、WebSockets和其他需要与每个用户建立长期连接的应用程序的理想选择。

Tornado大致可分为三个主要部分:

  • web框架(包括创建web应用程序的子类RequestHandler和各种支持类)。
  • HTTP的客户端和服务器端实现(HTTPServer和AsyncHTTPClient)。
  • 一个异步网络库,包括IOLoop和IOStream类,它们是HTTP组件的构建块,也可用于实现其他协议。

Tornado web框架和HTTP服务器共同提供了WSGI的全栈替代方案。虽然可以将Tornado HTTP服务器用作其他WSGI框架的容器(WSGIContainer),但这种组合有局限性,要充分利用Tornado,您需要同时使用Tornado的web框架和HTTP服务器。

1.1线程与WSGI

Tornado不同于大多数Python web框架。它不是基于WSGI的,通常每个进程只运行一个线程。

虽然tornado.WSGI模块中提供了对WSGI的一些支持,但它不是开发的重点,大多数应用程序都应该直接使用tornado自己的接口(如tornado.web)来编写,而不是使用WSGI。

一般来说,Tornado代码不是线程安全的。Tornado中唯一可以从其他线程安全调用的方法是IOLoop.add_callback。您还可以使用IOLoop.run_in_executor在另一个线程上异步运行阻塞函数,但请注意,传递给run_in_excutor的函数应避免引用任何Tornado对象。run_in_executor是与阻塞代码交互的推荐方式。

1.2asyncio集成

Tornado与标准库asyncio模块集成在一起,并共享相同的事件循环(自Tornado 5.0以来默认)。一般来说,为asyncio设计的库可以与Tornado自由混合使用。

1.3安装

pip install tornado

Tornado列在PyPI中,可以用pip安装。请注意,源代码发行版包含以这种方式安装Tornado时不存在的演示应用程序,因此您可能希望下载源代码tar包的副本或克隆git存储库。

先决条件:Tornado 6.3需要Python 3.8或更高版本。以下可选软件包可能有用:

  • pycurl由可选的tornado.curlhttpclient使用。需要Libcurl 7.22或更高版本。
  • pycares是一种替代的非阻塞DNS解析器,可以在线程不合适时使用。

平台:Tornado专为类Unix平台设计,在支持epoll(Linux)、kqueue(BSD/macOS)或/dev/poll(Solaris)的系统上具有最佳性能和可扩展性。

Tornado也将在Windows上运行,尽管官方不支持或不建议在生产环境中使用此配置。Windows上缺少一些功能(包括多进程模式),可扩展性有限(尽管Tornado是在支持Windows的asyncio上构建的,但Tornado不使用Windows上可扩展网络所需的API)。

1.4示例

这是一个简单的 “Hello,world” Tornado网络应用程序示例:

import asyncio
import tornado

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

async def main():
    app = make_app()
    app.listen(8888)
    await asyncio.Event().wait()

if __name__ == "__main__":
    asyncio.run(main())

这个例子没有使用Tornado的任何异步功能。

1.5异步和非阻塞I/O

实时网络功能要求每个用户都有一个长期空闲的连接。在传统的同步web服务器中,这意味着为每个用户分配一个线程,这可能非常昂贵。

为了最大限度地降低并发连接的成本,Tornado使用了单线程事件循环。这意味着所有应用程序代码都应该以异步和非阻塞为目标,因为一次只能有一个操作处于活动状态。

异步和非阻塞这两个术语密切相关,经常可以互换使用,但它们并不完全相同。

1.5.1阻塞

函数在返回之前等待发生某些事情时会阻塞。一个函数可能会因多种原因而阻塞:网络I/O、磁盘I/O、互斥等。事实上,每个函数在运行和使用CPU时都会阻塞,至少有一点点(举一个极端的例子,说明为什么CPU阻塞必须像其他类型的阻塞一样受到重视,可以考虑像bcrypt这样的密码散列函数,其设计使用数百毫秒的CPU时间,远远超过典型的网络或磁盘访问)。

函数在某些方面可以是阻塞的,在其他方面可以是非阻塞的。在Tornado的背景下,我们通常在网络I/O的背景下谈论阻塞,尽管各种阻塞都要尽量减少。

1.5.2异步

异步函数在完成之前返回,通常会在触发应用程序中的某些未来操作之前在后台进行一些工作(与正常的同步函数不同,后者在返回之前会做所有要做的事情)。异步接口有很多风格:

  • 回调参数
  • 返回占位符(Future、Promise、Deferred)
  • 交付到队列
  • 回调注册表(例如POSIX信号)

无论使用哪种类型的接口,异步函数与调用者的交互方式都是不同的;没有免费的方法可以使同步函数以对调用者透明的方式异步(像gevent这样的系统使用轻量级线程来提供与异步系统相当的性能,但它们实际上并没有使事情异步)。

Tornado中的异步操作通常返回占位符对象(Futures),但使用回调的IOLoop等一些低级组件除外。占位符对象(Futures)通常使用wait或yield关键字转换为结果。

1.5.3示例

以下是一个同步函数示例:

from tornado.httpclient import HTTPClient

def synchronous_fetch(url):
    http_client = HTTPClient()
    response = http_client.fetch(url)
    return response.body

以下是作为本机协程异步重写的同一函数:

from tornado.httpclient import AsyncHTTPClient

async def asynchronous_fetch(url):
    http_client = AsyncHTTPClient()
    response = await http_client.fetch(url)
    return response.body

或者为了与旧版本的Python兼容,使用tornado.gen模块:

from tornado.httpclient import AsyncHTTPClient
from tornado import gen

@gen.coroutine
def async_fetch_gen(url):
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url)
    raise gen.Return(response.body)

协程有点神奇,但它们在内部的作用是这样的:

from tornado.concurrent import Future

def async_fetch_manual(url):
    http_client = AsyncHTTPClient()
    my_future = Future()
    fetch_future = http_client.fetch(url)
    def on_fetch(f):
        my_future.set_result(f.result().body)
    fetch_future.add_done_callback(on_fetch)
    return my_future

请注意,协程在获取完成之前返回其Future。这就是协程异步的原因。

你可以用协程做任何事情,也可以通过传递回调对象来做,但协程通过让你以同步的方式组织代码,提供了一个重要的简化。这对于错误处理尤其重要,因为try/except块在协程中的工作方式与您所期望的一样,而这在回调中很难实现。

1.6协程

在Tornado中,推荐使用协程编写异步代码。协程使用Python的wait关键字来暂停和恢复执行,而不是一系列回调(在gevent等框架中看到的协作轻量级线程有时也被称为协程,但在Tornado中,所有协程都使用显式上下文开关,被称为异步函数)。

协程几乎和同步代码一样简单,但没有线程的开销。它们还通过减少可能发生上下文切换的地方的数量,使并发性更容易推理。

例子:

async def fetch_coroutine(url):
    http_client = AsyncHTTPClient()
    response = await http_client.fetch(url)
    return response.body

1.6.1原生协程与装饰器协程

Python 3.5引入了async和wait关键字(使用这些关键字的函数也称为“原生协程”)。为了与旧版本的Python兼容,您可以使用tornado.gen.coroutine装饰器使用“装饰”或“基于yield”的协程。

只要有可能,建议使用原生协程。仅在需要与旧版本的Python兼容时使用装饰器协程。Tornado文档中的示例通常会使用原生形式。

这两种形式之间的翻译通常很简单:

# 装饰器:                        # 原生:

# Normal function declaration
# with decorator                # "async def" keywords
@gen.coroutine
def a():                        async def a():
    # "yield" all async funcs       # "await" all async funcs
    b = yield c()                   b = await c()
    # "return" and "yield"
    # cannot be mixed in
    # Python 2, so raise a
    # special exception.            # Return normally
    raise gen.Return(b)             return b

下面概述了这两种协程形式之间的其他差异。

  • 原生协程:
    • 通常更快。
    • 可以使用async for和async with语句,这使一些模式变得简单得多。
    • 除非你 await 或 yield,否则根本不执行。一旦调用,修饰后的协程就可以在“后台”开始运行。请注意,对于这两种协程,使用 wait 或 yield 都很重要,这样任何异常都有地方可抛出。
  • 装饰器协程:
    • 与consident.futures包进行额外集成,允许直接生成executor.submit的结果。对于原生协程,请改用IOLoop.run_in_executor。
    • 通过生成列表或字典来支持等待多个对象的简略表达方式。在原生协程中使用tornado.gen.multi来实现这一点。
    • 可以通过转换函数注册表支持与包括Twisted在内的其他软件包的集成。要在原生协程中访问此功能,请使用tornado.gen.convert_generated。
    • 始终返回Future对象。原生协程返回一个不是Future的可唤醒对象。在Tornado中,两者大多可以互换。



相关推荐

MFC、Qt、WPF?该用哪个?(mfc和wpf区别)

MFC、Qt和WPF都是流行的框架和工具,用于开发图形用户界面(GUI)应用程序。选择哪个框架取决于你的具体需求和偏好。MFC(MicrosoftFoundationClass)是微软提供的框架,...

一款WPF开发的通讯调试神器(支持Modbus RTU、MQTT调试)

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!项目介绍Wu.CommTool是一个基于C#、WPF、Prism、MaterialDesign...

关于面试资深C#、WPF开发工程师的面试流程和问题

一、开场(2-3分钟)1.欢迎应聘者,简单介绍公司和面试流程。2.询问应聘者是否对公司或岗位有初步的问题。二、项目经验与技术应用(10-20分钟)1.让应聘者详细介绍几个他参与过的C#、...

C# WPF MVVM模式Prism框架下事件发布与订阅

01—前言处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Prism提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间通过事件进行...

WPF 机械类组件动画制作流程简述(wps上怎么画机械结构简图)

WPF机械类组件动画制作流程简述独立观察员2025年3月4日一、创建组件创建组件用户控件,将组件的各部分“零件”(图片)拼装在一起,形成组件的默认状态:二、给运动部分加上Rend...

C#上位机WinForm和WPF选哪个?工控老油条的"血泪史"

作为一个从互联网卷进工控坑的"跨界难民",在这会摸鱼的时间咱就扯一下上位机开发选框架这档子破事。当年我抱着WPF的酷炫动画一头扎进车间,结果被产线老师傅一句"你这花里胡哨的玩意...

【一文扫盲】WPF、Winform、Electron有什么区别?

近年来,随着软件开发的不断发展,开发人员面临着选择适合他们项目的各种框架和工具的挑战。在桌面应用程序开发领域,WPF、Winform和Electron是三个备受关注的技术。本文将介绍这三者的区别,帮助...

一个开源、免费、强大且美观的WPF控件库

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!项目介绍HandyControl是一套基于WPF(WindowsPresentationF...

WPF 根据系统主题自动切换浅色与深色模式

WPF根据系统主题自动切换浅色与深色模式控件名:Resources作者:WPFDevelopersOrg-驚鏵原文链接[1]:https://github.com/WPFDevelopers...

WPF与WinForm的本质区别(wpf与maui)

在Windows应用程序开发中,WinForm和WPF是两种主要的技术框架。它们各自有不同的设计理念、渲染机制和开发模式。本文将详细探讨WPF与WinForm的本质区别,并通过示例进行说明。渲染机制W...

Win10/Win11效率神器再进化:微软发布PowerToys 0.90.0版本

IT之家4月1日消息,微软今天(4月1日)更新PowerToys,在最新发布的0.90.0版本中,修复多个BUG之外,引入多项功能更新,为Windows10、Windows...

一款非常漂亮的WPF管理系统(wpf架构及特性)

我们致力于探索、分享和推荐最新的实用技术栈、开源项目、框架和实用工具。每天都有新鲜的开源资讯等待你的发现!WPFManager项目介绍该项目是一款WPF开发的管理系统,数据库采用的MSSqlserv...

WPF 实现描点导航(wpf按钮的点击事件)

WPF实现描点导航控件名:NavScrollPanel作者:WPFDevelopersOrg-驚鏵原文链接[1]:https://github.com/WPFDevelopersOrg/WPF...

微软更新基于Win11的Validation OS 2504:增强 .NET与WPF

IT之家5月1日消息,科技媒体NeoWin今天(5月1日)发布博文,报道称微软公司更新基于Windows11的ValidationOS,增强支持.NET和WPF,并优...

WPF的技术架构与优势(wpf的前景)

WindowsPresentationFoundation(WPF)是一个现代化的用户界面框架,专为构建Windows应用程序而设计。它通过分层的技术架构和丰富的功能集,提供了全面的应用程...

取消回复欢迎 发表评论: