104.协程
Posted tk-tank
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了104.协程相关的知识,希望对你有一定的参考价值。
协程
- 定义:为非抢占式多任务产生子程序的计算机程序组件
- 协程允许不同入口点在不同位置暂停或开始执行程序
- 从技术角度讲,协程是可以暂停的函数,或直接理解为生成器
- 本质是单线程,相比多线程,可以及其节省系统资源
- 协程函数运行结束后,如果还执行.send()就会报错StopIteration
- yield即使返回值,也是可以是下一步的参数输入值
def xc():
print("协程开始")
#yield既是出口,也是入口
a = yield
print("协程从新开始:", a)
#实例一个协程
x = xc()
print("11111")
#此步骤可以使用next(x)
#开始执行,也叫预激
x.send(None)
print("22222")
x.send("haha")
inspect.getgeneratorstate(x) 查询协程的状态(inspect模块)
- ‘GEN_CREATED‘ 等待开始执行。
- ‘GEN_RUNNING‘ 解释器正在执行。
- ‘GEN_SUSPENDED‘ 在 yield 表达式处暂停。
- ‘GEN_CLOSED‘ 执行结束。
协程终止
- 协程中文处理的异常,会向上传递给next或.seed方法的调用方
- 止协程的另一种方法:发送哨符值,让协程推出,一内置的None或Ellipsis
yield from
- 委派生成器
- 包含yield from的生成器函数
def A():
for i in [1, 2]:
yield i
print(list(A()))
def B():
#相当于在list和[1, 2]间的中间地带
yield from [1, 2]
print(list(B()))
asyncio包
- python3.4开始引入便准库,内置对异步IO的支持
- asyncio本身是一个消息循环
- 创建过程:
- 创建消息循环
- 把协程引入
- 关闭消息循环
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
#跳出协程,睡5秒
yield from asyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
#启动消息循环
loop = asyncio.get_event_loop()
#定义要执行的任务
tasks = [hello(), hello()]
#asyncio使用wati等待task执行完毕
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
#执行结果
Hello world! (<_MainThread(MainThread, started 2400)>)
Hello world! (<_MainThread(MainThread, started 2400)>)
Hello again! (<_MainThread(MainThread, started 2400)>)
Hello again! (<_MainThread(MainThread, started 2400)>)
async 和 await
- python3.5引入
- 更好的表示异步io
- 让协程代码更简洁
- 在语法上可以简单的替换
- async 替换 @asyncio.coroutine
- await 替换 yield from
aidhttp
- asyncio可以实现单线程并发IO操作
- 客户端用处不大
- 在服务器端,可以处理多用户的高并发用coroutine+单线程
- asyncio实现了TCP.UDP.SSL等协议
- aiohttp是给予asyncio的http框架
- 不是标准模块,需安装
concurrent.futures
- python3库
- 线程池
-利用multiprocessiong实现真正的并行计算,前提是cup得是多核 - 原理已子进程的形式,并行运行多个python解释器,子进程和主进程是相互独立的,所以他们的全局解释器锁是相互独立的,每个子进程都能完整的使用一个cup内核
- from concurrent.futures import ThreadPoolExecutor
- ThreadPoolExecutor(max_workers=数量) 创建线程池,并指定线程数量,根据需要选择
- ProcesspoolExecutor(max_workers=数量) 创建进程池,并指定进程数量,根据需要选择
- .submit(fn, args, kwargs) 创建线程或进程 fn线程或进程函数的函数名
- .done 线程执行的状态 Ture执行完毕, False未执行完毕
- .result 线程或进程函数执行的结果
import time
from concurrent import futures
def return_futures(a):
time.sleep(2)
return a
#创建一个线程池,max_workers工作线程数量
s = futures.ThreadPoolExecutor(max_workers=2)
#向线程池中加入两个任务
r1 = s.submit(return_futures, "hi")
r2 = s.submit(return_futures, "hello")
#判断两个线程执行状态
print(r1.done())
print(r2.done())
time.sleep(3)
print(r1.done())
print(r2.done())
#输出两个线程的结果
print(r1.result())
print(r2.result())
- .map()
- 和map函数类似,映射
- 异步执行
import time
from concurrent import futures
def wait_on(a):
print(a)
time.sleep(2)
return "ok"
l = [1, 2]
t = futures.ThreadPoolExecutor(max_workers=2)
for i in t.map(wait_on, l):
print(i)
以上是关于104.协程的主要内容,如果未能解决你的问题,请参考以下文章