1.协程概念

 

  • 能够在一个线程下的多个任务之间来回切换,那么每一个任务就是协程

进程和线程的切换是由操作系统控制切换

协程和线程
#共同点:
    -线程和协程的创建,切换销毁都需要时间开销,
    -在cpython中线程和协程都不能利用多个cpu(只能并发)
#不同点:
    -多线程线程的切换是由操作系统完成,而协程的切换是通过代码实现,操作系统不可见
    -多线程创建,切换销毁时间开销较大,协程的时间开销很小,携程切换用户可操作性,不会增加操作系统压力

2.协程操作(模块)

  • 线程切换
  • 两种切换方式
两种切换方式
    # 原生python完成   yield  asyncio
    # C语言完成的python模块  greenlet  gevent
  • 原生python代码实现 (asyncos 模块)- asyncos利用yield记录线程代码执行状态和位置,但是yield不能规避io操作
  • C语言完成的PYthon模块(#greenlet模块)
  • 规避IO操作,切换原理(了解)

     

2.1 gevent 第三方模块

  • 基本格式
import time
import gevent
from gevent import monkey           
monkey.patch_all()              #用mokey模块使协程识别多次使用的外部方法,比如time.time()
def eat():
    print('wusir is eating')
    time.sleep(1)
    print('wusir finished eat')

def sleep():
    print('小马哥 is sleeping')
    time.sleep(1)
    print('小马哥 finished sleep')

# g1 = gevent.spawn(eat)   # 创造一个协程任务
# g2 = gevent.spawn(sleep)   # 创造一个协程任务
# print(g1.value)
# print(g2.value)
# # g1.join()   # 阻塞 直到g1任务完成为止
# # g2.join()   # 阻塞 直到g1任务完成为止
# gevent.joinall([g1,g2,g3])        #知道列表内的协程任务全部终止为止
g_l = []
for i in range(10):
    g = gevent.spawn(eat)
    g_l.append(g)
gevent.joinall(g_l)
  • 接收返回值
  • value
# g1 = gevent.spawn(eat)  # 创造一个协程任务
# g2 = gevent.spawn(sleep)  # 创造一个协程任务 
# print(g2.value)

2.2 asyncio 内置模块(记住启动一个/多个线程)

  • async-异步 sync-同步
  • asyncio 协程基本格式
#起一个任务

import asyncio          #插入asyncio模块
async def demo():       #创建async函数
      print('start')
      await asyncio.sleep(1)    #阻塞,阻塞必须写入await之后   且使用asyncio模块自己的方法
      print('end')
  loop = asyncio.get_event_loop()   #创建一个第三方事件循环,监测是否IO
  loop.run_until_complete(demo())       #吧demo任务丢到事件循环中去执行
#起多个任务,且没有返回值

import asyncio
  
async def demo():
    print('start')
    await asyncio.sleep(1)  #阻塞,阻塞必须写入await之后   且使用asyncio模块自己的方法
    print('end')

loop = asyncio.get_event_loop()
wait_obj=asyncio.wait([demo(),demo(),demo()])
loop.run_until_complete(wait_obj)

 

#起多个任务,有返回值,可以绑定回调函数
  
  import asyncio 
  asrnc def demo():
    print('start')
      await asyncio.sleep(1)    #阻塞,阻塞必须写入await之后   且使用asyncio模块自己的方法
      print('end')
      retunrn 123
  
  loop = asyncio.get-event_loop()
  t1 = loop.create_task(demo())
  t2 = loop.create_task(demo())
  tasks=[t1,t2]
  wait_obj=asyncio.wait([t1,t2])
  loop.run_until_complete(wait_obj)
  for i in easks:
  print(tasks.result())

 

  • asyncos是python原生的底层的协程模块
  • 爬虫,webserver框架
  • 爬虫网络编程的效率和并发效果
  • await 阻塞必须写在await之后,告诉协程函数这里要切换出去,还能保证一会再切回来
  • await 必须写在async函数里,async是协程函数
  • loop 时间循环
  • 所有的协程的执行,调度都离不开这个loop