[Python 多线程] asyncio (十六)
asyncio
该模块是3.4版本加入的新功能。
先来看一个例子:
def a():
for x in range(3):
print('a.x', x) def b():
for x in 'abc':
print('b.x', x) a()
b() #运行结果:
a.x 0
a.x 1
a.x 2
b.x a
b.x b
b.x c
这个例子是一个典型的串行程序,两个函数调用是在主线程中顺序执行。
有以下几种方法可以让这段程序改为并行:
1. 生成器
2. 多线程
3. 多进程
4. 协程
1)生成器方法:
def a():
for x in range(3):
yield x def b():
for x in 'abc':
yield x m = a()
n = b() for _ in range(3):
print(next(m))
print(next(n)) #运行结果:
0
a
1
b
2
c
使用生成器来实现交替执行。这两个函数都有机会执行,这样的调度不是操作系统的进程、线程完成的,而是用户自己设计的。
2)多线程方法:
import threading,time def a():
for x in range(3):
time.sleep(0.0001)
print('a.x',x) def b():
for x in 'abc':
time.sleep(0.0001)
print('b.x',x) threading.Thread(target=a).start()
threading.Thread(target=b).start() #运行结果:
a.x 0
b.x a
a.x 1
b.x b
a.x 2
b.x c
主要使用sleep函数强制切换来实现伪并行。
3)多进程方式:
import multiprocessing def a():
for x in range(3):
print('a.x',x) def b():
for x in 'abc':
print('b.x',x) if __name__ == '__main__':
multiprocessing.Process(target=a).start()
multiprocessing.Process(target=b).start() #运行结果:
a.x 0
a.x 1
a.x 2
b.x a
b.x b
b.x c
多进程方式才是真正的并行。
4)协程方法:
协程,需要使用到 asyncio 标准库,是Python3.4版本加入的新功能,底层基于selectors实现,包括异步IO、事件循环、协程等内容。
事件循环:
事件循环是asyncio提供的核心运行机制。
程序开启一个无限的循环,使用者会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。
4.1 事件循环基类
asyncio.BaseEventLoop 这个类是一个实现细节,它是asyncio.AbstractEventLoop的子类,不可以直接使用
asyncio.AbstractEventLoop 事件循环的抽象基类,这个类是是线程不安全的
4.2 运行事件循环
asyncio.get_event_loop() 返回一个事件循环对象,是asyncio.BaseEventLoop的实例
asyncio.AbstractEventLoop.stop() 停止运行事件循环
asyncio.AbstractEventLoop.run_forever() 一直运行,直到调用stop()
asyncio.AbstractEventLoop.run_until_complete(future) 运行直到future对象运行完成,返回结果
asyncio.AbstractEventLoop.close() 关闭事件循环
asyncio.AbstractEventLoop.is_running() 返回事件循环的运行状态
asyncio.AbstractEventLoop.is_closed() 如果事件循环已关闭,返回True
4.3 协程
协程不是进程、也不是线程,它是用户空间调度完成并发处理的方式。(同一线程内交替执行其实也是伪并发)
并发指的是在一段时间内做了多少、并行指的是同一时刻有多少同时执行。
进程、线程由操作系统完成调度,而协程是线程内完成调度。它不需要更多的线程,也就没有多线程切换带来的开销。
协程是非抢占式调度,只有一个协程主动让出控制权,另一个协程才会被调度。
协程也不需要锁机制,因为是在同一线程中执行。
多CPU下,可以使用多线程和协程配合,既能进程并发又能发挥协程在单线程中的优势。
Python中协程是基于生成器的。
4.4 协程的使用
4.4.1 Python3.4中使用@asyncio.coroutine 、 yield from
#asyncio Python3.4 import asyncio @asyncio.coroutine
def foo(x): #生成器函数上面加了协程装饰器之后就转化成协程函数
for i in range(3):
print('foo {}'.format(i))
yield from asyncio.sleep(x) #调用另一个生成器对象 loop = asyncio.get_event_loop() #获得一个时间循环
loop.run_until_complete(foo(1)) #传入一个生成器对象的调用
loop.close() #运行结果:
foo 0
foo 1
foo 2
[Finished in 3.3s]
此例子在一个生成器函数加了协程装饰器之后,该生成器函数就转化成了协程函数。
4.4.2 Python3.5中使用关键字 async def 、 await ,在语法上原生支持协程
#asyncio Python3.5 import asyncio async def foo(x): #异步定义,协程定义
for i in range(3):
print('foo {}'.format(i))
await asyncio.sleep(x) #不可以出现yield,使用await替换 print(asyncio.iscoroutinefunction(foo))
loop = asyncio.get_event_loop()
loop.run_until_complete(foo(1)) #传入一个协程对象的调用
loop.close() #运行结果:
True
foo 0
foo 1
foo 2
[Finished in 3.3s]
async def 用来定义协程函数,iscoroutinefunction(func)判断func函数是否是一个协程函数。协程函数中可以不包含await、async关键字,但不能使用yield关键字。
其它语法:async with,支持上下文的协程
4.4.3 coroutine asyncio.wait(futures, *, loop=None, timeout=None, return_when=ALL_COMPLETED)
等待futures序列中的协程对象执行完成,futures序列不可以为空。
timeout可以用于控制返回前等待的最大秒数,秒数可以是int或浮点数,如果未指定timeout,则无限制。
#wait多个协程对象
import asyncio @asyncio.coroutine
def a():
for i in range(3):
print('a.x',i)
yield @asyncio.coroutine
def b():
for i in range(3):
print('b.x',i)
yield loop = asyncio.get_event_loop()
tasks = [a(),b()]
loop.run_until_complete(asyncio.wait(tasks)) #传入一个协程对象序列 loop.close() #运行结果:
b.x 0
a.x 0
b.x 1
a.x 1
b.x 2
a.x 2
[Finished in 0.3s]
总结:
传统的多线程、多进程都是系统完成调度,而协程是在进程中的线程内由用户空间调度完成并发处理,主要依靠生成器来实现交替调度。
Python3.4中使用@asyncio.coroutine、yield from调用另一个生成器对象
Python3.5中使用关键字 async def 和 await,且不可以出现yield关键字。
[Python 多线程] asyncio (十六)的更多相关文章
- “全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十六章:同步synchronized关键字详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 进击的Python【第十六章】:Web前端基础之jQuery
进击的Python[第十六章]:Web前端基础之jQuery 一.什么是 jQuery ? jQuery是一个JavaScript函数库. jQuery是一个轻量级的"写的少,做的多&quo ...
- python 教程 第十六章、 正则表达式
第十六章. 正则表达式 1) 匹配多个表达式 记号 re1|re2 说明 匹配正则表达式re1或re2 举例 foo|bar 匹配 foo, bar 记号 {N} 说明 匹配前面出 ...
- python学习笔记(十六)-Python多线程多进程
一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...
- 跟着刚哥梳理java知识点——多线程(十六)
创建多线程第一种方式:① 继承:继承Thread.② 重写:重写Thread类的run()方法③ 创建:创建一个子类的对象④ 调用:调用线程的start()方法,启动此线程,调用run()方法 cla ...
- Python 学习 第十六篇:networkx
networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法.图是由顶点.边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系.顶点和边 ...
- python 学习笔记十六 django深入学习一 路由系统,模板,admin,数据库操作
django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ ...
- [Python笔记]第十六篇:web框架之Tornado
Tornado是一个基于python的web框架,xxxxx 安装 python -m pip install tornado 第一个Tornado程序 安装完毕我们就可以新建一个app.py文件,放 ...
随机推荐
- block中self关键字的使用-防止self 被retain一次
在代码块中使用对象的成员时(成员变量是属性strong,MRC估计是retain时效果一样,使用方法时也一样): 警告: capturing self strongly in this block i ...
- 微信小程序通过CODE换取session_key和openid
微信小程序的用户信息获取需要请求微信的服务器,通过小程序提供的API在小程序端获取CODE,然后将CODE传入到我们自己的服务器,用我们的服务器来换取session_key和openid. 小程序端比 ...
- MapReduce详解和WordCount模拟
最早接触大数据,常萦绕耳边的一个词「MapReduce」.它到底是什么,能做什么,原理又是什么?且听下文讲解. 是什么 MapReduce 即是一个编程模型,又是一个计算框架,它充分采用了分治的思想, ...
- Linux 中文乱码
开发中不免会接触到linux,Linux系统中文语言乱码也是我们常碰到的一个问题之一. 在网上查找了不少资料,参考了https://www.linuxidc.com/Linux/2017-07/145 ...
- mybatis 排坑记录
1. mapper xml resultMap 中定义 property 时不能出现空格 否则会出现反射错误,找不到 do 对应的 set 方法
- 错误:Attempted to load applicationConfig: [classpath:/application.yml] but snakeyaml was not found on the classpath
MyEclipse导入工程,报错如下: ::42.187 [main] ERROR org.springframework.boot.SpringApplication - Application r ...
- 通过vertical-align属性实现“竖向居中”显示
自学编程大概有大半年的时间了,从15年7月开始学习使用人数最多的JAVA,到后来喜欢上了前端,但由于之间在建筑设计院的工作加班颇为频繁,每天刨去工作,基本没有多少自己个人的时间,只能每天6,7点起床, ...
- No rabbit death problem
package basic.java; /** * 不死神兔问题: * 有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,加入兔子都不死,问地二十个月的兔子对数 ...
- Ubuntu 安装 PhpMyAdmin 图文教程
Ubuntu 安装 PhpMyAdmin 管理 MySQL 数据库 PhpMyAdmin 是一个用 PHP 编写的软件工具,可以通过 web方式控制和操作 MySQL 数据库.通过 phpMyAdmi ...
- weex常用属性梳理
之前发了一篇weex集成和开发的博客,主要是讲了weex开发环境的搭建和文件的编译.部署,还有就是一些个人对weex的理解,最近将原生的项目改造成weex的项目,也持续了有两个多月的时间了,后面我会发 ...