上篇文章写了关于yield from的用法,简单的了解异步模式,【上次的内容连接】此次让咱们经过一个有趣例子带你们了解asyncio基本使用。python
1.经过不停的依次顺序迭代"|/-\"中的一个字符。
2.每次输出前使用退格符模拟一个动态效果。所谓的退格符就是删除上一个字符串,并在原来的位置输出新的字符串。
代码实现:缓存
1 import itertools
2 import sys
3 import time
4 flush=sys.stdout.flush
5 for i in itertools.cycle("|/-\\"):
6 print('\b'*len(i)+i,end='')
7 flush()
8 time.sleep(.1)
复制代码
1,2,3行导入须要的包。bash
4行定义7行调用,强制刷新缓存。
当咱们打印一些字符时,并非调用print函数后就当即打印的。
通常会先将字符送到缓冲区,而后再打印。这就存在一个问题,
若是你想等时间间隔的打印一些字符,
但因为缓冲区没满,不会打印。就须要采起强制刷新等手段了。异步
5行,使用itertools.cycle无穷的迭代括号内的字符串。async
6行,print默认是print(end='\n'),这里修改其默认方法end='',不换行。
关键做用的是'\b','\b'*len(i)表示屡次退格,长度由迭代的字符的个数决定。函数
8行 模拟休眠0.1秒。
这里只是一个简单的效果演示,下面咱们使用一个使用协程的例子。oop
该例子参考流畅的python,我对其做了部分修改。先看代码,后面再作解释。学习
# -*- coding: utf-8 -*-
# @Time : 2018/12/19 9:08 PM
# @Author : cxa
# @File : 18-2.py
# @Software: PyCharm
# 经过协程以动画形式显示文本式旋转指针
import asyncio
import itertools
import sys
import time
async def spin(msg): # (1)
write, flush = sys.stdout.write, sys.stdout.flush # (2)
for char in itertools.cycle('|/-\\'): #(3)
status = char + ' ' + msg
print(status, end='')
flush() #(4)
# write('\b' * len(status)) # (5)
print('\b' * len(status), end='') # (6)
try:
await asyncio.sleep(.1) # (7)
except asyncio.CancelledError: # (8)
break
# write(" " * len(status) + '\b' * len(status)) # (9)
print(" " * len(status) + '\b' * len(status), end='') # (10)
async def slow_function():
# 伪装等待io一段时间
await asyncio.sleep(3)
return "very good!"
async def supervisor():
# loop = asyncio.get_event_loop() # (11)
# spinner = loop.create_task(spin('thking!')) # (12)
spinner = asyncio.ensure_future(spin('thking!')) # (13)
print('spinner object:', spinner) # (14)
result = await slow_function() # (15)
spinner.cancel() # (16)
return result
def main():
loop = asyncio.get_event_loop() # (17)
result = loop.run_until_complete(supervisor()) # (18)
loop.close()# (19)
print("Result:", result)
if __name__ == '__main__':
main()
复制代码
下面对上面编号进行一一讲解。
首先导入必须的包,其中asyncio就是咱们要使用的协程包。
(1)def表明一个函数或者方法,若是在前面加async def这个就变成协程了。再也不是一个方法。
在python3.4的时候经过使用@asyncio.coroutine来修饰一个函数使其变为一个协程。如今不推荐使用。动画
(2) 定义对象方便后面使用。ui
(3)itertools.cycle会把一个可迭代对象无限重复下去。
(4)强制刷新缓存
(5)(6)这两个是等价的:
当咱们在使用print的时候,其实是调用了 sys.stdout.write(obj+'\n'),print在打印时会自动加个换行符。
这里就是一开始说的使用指定字符串长度的退格符
(7)咱们使用asyncio.sleep函数来模拟IO操做。
(8)执行(16)的时候触发。
(9)(10)这两个是等价的,输出最后的显示结果。
(11)(12)这两句能够用(13)来替代使用asyncio.ensure_future(coroutine)
和 loop.create_task(coroutine)均可以建立一个task。
(14) 输出的是一个协程对象
(15)使用await把控制权交给主循环,以便loop调用其余的协程。
(16)Task对象能够取消,取消后会在协程当前暂停的yield处抛出asyncio.CancelledError异常。
(17)(18) asyncio.get_event_loop方法能够建立一个事件循环,
而后使用run_until_complete将协程注册到事件循环,并启动事件循环。协程的返回值是此次调用的返回值。
(19)结束循环。
流畅的python 第16章
关于asyncio的后续的一些使用请关注公众号:python学习开发。