博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网站搭建笔记精简版---廖雪峰WebApp实战-Day2:编写Web App骨架笔记
阅读量:4165 次
发布时间:2019-05-26

本文共 4475 字,大约阅读时间需要 14 分钟。

网站搭建笔记精简版-廖雪峰教程学习@[三川水祭]

仅作学习交流使用,将来的你会感谢现在拼命努力的自己!!!

目录

什么是IO

异步IO的背景知识
Web app骨架搭建
asyncio函数与aiohttp函数详解

什么是IO

IO意思是输入与输出,本地是内存,外地是磁盘或网页,本地往外地发送数据叫做输出Output,本地接收外地发送的数据叫做Input。IO包括同步IO与异步IO。举个栗子,背景是内存往磁盘写数据,内存输出这个数据需要0.1s,而磁盘接收这个数据需要10s

同步IO:当内存输出完数据后,处于等待状态,等磁盘接收完数据后继续执行接下来的步骤
异步IO:当内存输出完数据后,懒得等磁盘慢悠悠的写,就直接搞别的事情去了,等磁盘写完后,通知内存,然后内存才与磁盘继续往下执行项目。
而磁盘通知内存有两种方式,分别为回调模式与轮询模式。
回调模式:磁盘直接过去调用内存,开展下一步工作。
轮询模式:磁盘发个信息给内存,告诉内存已经完成工作,可开展下一步工作了,而内存在搞别的事情的时候则需要时不时的看一下消息,确定磁盘是否完成。当接收到消息后,才与磁盘共同开展下一步工作。

异步IO背景知识

面临问题:CPU执行速度高而IO设备执行速度低(龟速)。

解决方法:多线程和多进程、异步IO。
多线程的缺点:当线程数量较多时候,CPU资源主要用在线程之间的切换上,真正搞代码的资源少,性能严重下降。
进程:系统进行资源分配和调度的一个独立单位,有自己的内存空间
线程:是CPU调度和分派的基本单位,共享进程内存资源。
协程:使用yield函数,不断的在子程序之间进行切换的单条线程。是一种轻量级的线程,可以在不加锁的情况下访问全局变量。
迭代器:iter函数,迭代的对象从第一个元素开始访问,直到所有元素访问完后才可结束,或者通过StopIteration强制结束。对象可以使列表、元组和字符串。
生成器:yield函数,执行到当前进行阻塞,n = yield r的意思是当前函数接收到数据后将值传递给n,若n为None,则不执行,反之向下执行循环到该条函数处,阻塞,返回r,等待接收新一轮n值。
迭代器与生成器参考。网页下的评论有更详细的解释。

Web app骨架搭建

该部分使用asyncio处理异步IO编程,实现单线程并发操作。进而使用aiohttp网络框架创建TCP网络服务器,不断使用轮询模式接收浏览器相应,通过解析浏览器发过来的请求,寻找相应的coroutine类执行函数,返回相应的Body response。coroutine类表示可并发且带有生成器的执行函数。

import logging; logging.basicConfig(level=logging.INFO)import asyncio, os, json, timefrom datetime import datetimefrom aiohttp import web# 将生成器index函数标记为coroutineasync def index(request):    # 相应的格式,注意加上content_type='text/html'属性,否则会显示为下载文件。    return web.Response(body=b'

Awesome

', content_type='text/html')async def init(loop): app = web.Application(loop=loop) # 链接index函数与‘/'对象,当接收到GET '/'时候,延迟两秒,服务器返回Index。 app.router.add_route('GET', '/', index) # 创建TCP服务,等待请求。 srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000) # 生成日志信息 logging.info('server started at http://127.0.0.1:9000...') return srv# 使用轮询模式保证协程执行loop = asyncio.get_event_loop()# s使用init函数创建TCP服务,等待浏览器链接,并使用相关函数进行相应。loop.run_until_complete(init(loop))# 一直等着浏览器的链接请求。loop.run_forever()

asyncio函数与aiohttp函数详解

asyncio函数:实现异步IO编程的函数。可利用一下代码进行实验。可参考。

import asyncio# async等价于@asyncio.coroutine,将wget这个generator函数标记为coroutine对象# 之后将该协程对象扔到get_event_loop函数中执行,实现异步IO操作。async def wget(host):    print('wget %s...' % host)    connect = asyncio.open_connection(host, 80)    # 调用connect,返回读与写两个IO,分别负责本地接收网页发送的消息与向网页发送消息两种模式。    # await类似于yield from生成器    reader, writer = await connect    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host    writer.write(header.encode('utf-8'))    # drain函数就是将write到缓存区的东西flush一下,提交给网页。    await writer.drain()    while True:        # 循环读取网页返回来的信息        line = await reader.readline()        # 可查看读取的具体信息是什么        #print(line)        # 当读到'\r\n'时候代表网页相应头已经读取完成,之后就是body部分。        if line == b'\r\n':            break        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))    # Ignore the body, close the socket    writer.close()# 使用轮询模式保证协程执行loop = asyncio.get_event_loop()# 将多个coroutine对象封装成一个Task任务列表tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]# 使用asyncio.wait(task)将任务并发执行。loop.run_until_complete(asyncio.wait(tasks))loop.close()

aiohttp:aiohttp则是基于asyncio实现的HTTP框架,直接调用里面的函数就可使实现简单的本地HTTP服务器搭建。可利用一下代码进行实验。想了解具体机制的参考,想了解函数中add_route机制的参考。

import logging; logging.basicConfig(level=logging.INFO)import asynciofrom aiohttp import web# 将生成器index函数标记为coroutineasync def index(request):    # 延时两秒后继续执行之后的步骤    await asyncio.sleep(2)    # 相应的格式,注意加上content_type='text/html'属性,否则会显示为下载文件。    return web.Response(body=b'

Index

', content_type='text/html')# 将生成器hello函数标记为coroutineasync def hello(request): # 延时两秒后继续执行之后的步骤 await asyncio.sleep(2) text = '

hello, %s!

' % request.match_info['name'] # 相应的格式,head会自动生成,自己负责写body即可。 return web.Response(body=text.encode('utf-8'), content_type='text/html')# 将生成器init函数标记为coroutineasync def init(loop): app = web.Application(loop=loop) # 链接index函数与‘/'对象,当接收到GET '/'时候,延迟两秒,服务器返回Index。 app.router.add_route('GET', '/', index) # 链接index函数与‘/hello/{name}'对象,当接收到GET '/hello/{name}'时候, # 延迟两秒,服务器取出{name}对象,并构造新的body进行返回。 app.router.add_route('GET', '/hello/{name}', hello) # 创建TCP服务,等待请求。 srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000) # 显示日志信息。 logging.info('server started at http://127.0.0.1:9000...') return srv# 使用轮询模式保证协程执行loop = asyncio.get_event_loop()# s使用init函数创建TCP服务,等待浏览器链接,并使用相关函数进行相应。loop.run_until_complete(init(loop))# 一直等着浏览器的链接请求。loop.run_forever()

在浏览器输入localhost:8000,等两秒,网页会接收到返回信息并显示为index。接下来在浏览器输入localhost:8000/hello/handsome,等两秒,网页显示hello, handsome!。

参考博客

转载地址:http://dmlxi.baihongyu.com/

你可能感兴趣的文章
架构师的职责都有哪些?
查看>>
看女程序员是怎么坑大师兄的, 网友: 真的惨,笑死我了!
查看>>
C/C++程序员面试基础知识(一)
查看>>
程序员提离职遭领导威胁,一线企业总监我都认识,我让你混不下去
查看>>
朝九晚六吊打互联网企业,程序员:又开始无脑吹国企了!
查看>>
网友话数万元转行程序员,但是却没人要,网友:是学历问题吗?
查看>>
程序员辞掉30W年薪接私活:6个月就能赚回30W,庆幸自己当初辞职
查看>>
马云四天三谈996被骂上热搜:抱歉,这届年轻人不好“骗”了!
查看>>
中国牛逼的程序员有哪些?入职华为两天转正,半个月升主任
查看>>
为什么大学里的计算机老师,不去大公司当程序员呢?
查看>>
eclipse的java facets的runtimes如何删除tomcat?
查看>>
oracle序列的cache_size说明
查看>>
oracle中两个时间戳相减得到间隔毫秒数
查看>>
Oracle中将毫秒数转换为timestamp类型的两种方法
查看>>
mybatis配置and rownum< minus 查询第几行到第几行数据的sql原型和mybatis原型。
查看>>
oracle的concat函数使用问题。
查看>>
eclipse编辑状态下怎样让指定行左移或右移?
查看>>
plsql developer如何导入导出表结构和数据以及如何复制表结构和数据?
查看>>
oracle如何去除某个字段中两边的空格?
查看>>
plsql developer如何在窗口列表直接可以修改表格中的数据?
查看>>