python是一门解释性语言,在python编程中,我们定义了几个运行过程,A - B - C ,解释器按照顺序执行,A - B - C 然后执行完毕。但是程序的运行需要花费时间,再看上面的例子 ,假如A函数要运行 3s B函数要运行5s C函数要运行7s 现在计算运行时间 3+5+7为15s的运行时间。这时候我们会发现程序在A函数的时候,即使计算机还有资源,但是控制权并没有给B函数,导致B函数在A函数运行完成的时候才能正常运行,然后是C,这远远浪费了计算机的资源和时间。于是我们使用了协程,这是在python的官网中也非常推荐的实方法
——asyncio 模块
优点:优于多线程切换花费的资源,方便简化控制流,支持高并发编程。
缺点:不支持多线程,只能配合多进程使用。
python实现协程的方式有
1.yield 方式
def run(n=0):
#定义一个生成器函数
while True:
n = yield n
print('传入数值,开始执行')
a = run() #预激活状态
print(next(a))
print('*'*20)
print(a.send('传入一个值'))
看一下运行结果
0
********************
传入数值,开始执行
传入一个值
生成器函数在激活之后生成一个n 然后通过send()函数传入数据。在每次取出值的时候函数run都会在yield执行完之后停顿,等待下一次执行(下一次执行时在yield之后开始),主程序此时开始执行其他操作,实际上这就是一种协程序。
2.asyncio 模块
定义:
import asyncio
async def run_async():
print('这是一个协程!')
#协程对象 并没有执行
coroutine = run_async()
#创建一个时间循环
loop = asyncio.get_event_loop()
#运行协程
loop.run_until_complete(coroutine)
看一下运行结果
这是一个协程! #运行成功了
协程本身是不能直接运行的,必须通过run_until_complete帮协程包装成task任务对象,task任务是Future类的子类,所以其它协程可以等待任务完成,或当这些任务完成获取返回结果。
task实例:
mport asyncio
async def run_async():
print('这是一个协程!')
#协程对象 并没有执行
coroutine = run_async()
#创建一个时间循环
loop = asyncio.get_event_loop()
#创建task事件
task = loop.create_task(coroutine)
#把task事件注册到事件循环中,并运行
loop.run_until_complete(task)
运行结果:
这是一个协程! #运行成功
获取返回值
task任务在运行完成的时候,可以保存程序的运行结果,然后可以用该对象获取返回值。
async def run_async():
print('这是一个协程!')
return '协程运行的返回值!'
#协程对象 并没有执行
coroutine = run_async()
#创建一个时间循环
loop = asyncio.get_event_loop()
#创建task事件
task = loop.create_task(coroutine)
#把task事件注册到事件循环中,并运行
loop.run_until_complete(task)
#在运行完成的时候task保留程序运行的返回值,我们用task.result()获取返回值
print(task.result())
结果:
这是一个协程!
协程运行的返回值!
await 方法阻塞
import asyncio
async def run_async():
print('这是一个协程!')
await asyncio.sleep(3) #在这里我们用await 方法模拟程序运行阻塞时间
return '协程运行的返回值!'
#协程对象 并没有执行
coroutine = run_async()
#创建一个时间循环
loop = asyncio.get_event_loop()
#创建task事件
task = loop.create_task(coroutine)
#把task事件注册到事件循环中,并运行
loop.run_until_complete(task)
#获取返回值
print(task.result())
结果:
这是一个协程!
##手动一下在三秒之后
协程运行的返回值!
并发并行
实例:假设我们有两件事要做,第一件是烧水,第二件是做饭。
import time
import asyncio
start_time = time.time() #开始时间
def heat_water():
print('现在去烧水了!,用时2s')
time.sleep(2) #时间停滞2s
def cook():
print('现在去做饭了!,用时3s')
time.sleep(3) #时间停滞3s
heat_water()
cook()
end_time = time.time() #结束时间
run_time = end_time - start_time #计算
print('两件事一共用时%s'%run_time)
看一下运行结果
现在去烧水了!,用时2s
现在去做饭了!,用时3s
两件事一共用时5.001287221908569
我们会发现在程序一件一件去做的时候一共要花费的时间为 2+3
再看看协程
import time
import asyncio
start_time = time.time()
async def heat_water():
print('现在去烧水!要花费2s,烧水的时间可以去做饭!')
await asyncio.sleep(2)
print('水烧完了!')
async def cook():
print('把烧水搁置,现在去做饭!要花费3s')
await asyncio.sleep(3)
print('饭做好了!')
loop = asyncio.get_event_loop() #创建一个时间循环 loop
#把两个事件保存到task中
task = {
heat_water(),
cook()
}
loop.run_until_complete(asyncio.wait(task)) #asyncio.wait()方法实现并发
end_time = time.time()
run_time = end_time -start_time
print('做这两件事情的时间为:%s'%run_time)
运行结果
把烧水搁置,现在去做饭!要花费3s
现在去烧水!要花费2s,烧水的时间可以去做饭!
水烧完了!
饭做好了!
做这两件事情的时间为:3.0039124488830566
我们从这里可以看出来,两个事情一起做时间并不是3+2 而是cook时间3s,这样就是协程的优势所在。
——每一份梦想都应该被尊重
——每一次努力都会有回报
——加油吧少年