一个有趣的小例子,带你入门协程模块-asyncio

上篇文章写了关于yield from的用法,简单的了解异步模式,【https://www.cnblogs.com/c-x-a/p/10106031.html】这次让我们通过一个有趣例子带大家了解asyncio基本使用。

目标效果图

基本原理

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行导入需要的包。

4行定义7行调用,强制刷新缓存。

当我们打印一些字符时,并不是调用print函数后就立即打印的。

一般会先将字符送到缓冲区,然后再打印。这就存在一个问题,

如果你想等时间间隔的打印一些字符,

但由于缓冲区没满,不会打印。就需要采取强制刷新等手段了。

5行,使用itertools.cycle无穷的迭代括号内的字符串。

6行,print默认是print(end='\n'),这里修改其默认方法end='',不换行。

关键作用的是'\b','\b'*len(i)表示多次退格,长度由迭代的字符的个数决定。

8行 模拟休眠0.1秒。

这里只是一个简单的效果演示,下面我们使用一个使用协程的例子。

使用asyncio完成同样的功能

该例子参考流畅的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) 定义对象方便后面使用。

(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学习开发。

一个有趣的小例子,带你入门协程模块-asyncio的更多相关文章

  1. 一个少女心满满的例子带你入门canvas

    https://blog.csdn.net/sunshine940326/article/details/76572850 本文首发于我的个人博客:http://cherryblog.site/ gi ...

  2. [python]python 遍历一个list 的小例子:

    [python]python 遍历一个list 的小例子: mlist=["aaa","bbb","ccc"]for ss in enume ...

  3. Unity带参数的协程

    两种方法都可以传递参数,代码如下: using UnityEngine; using System.Collections; public class Test : MonoBehaviour { v ...

  4. Python并发编程之从生成器使用入门协程(七)

    大家好,并发编程 进入第七篇. 从今天开始,我们将开始进入Python的难点,那就是协程. 为了写明白协程的知识点,我查阅了网上的很多相关资料.发现很难有一个讲得系统,讲得全面的文章,导致我们在学习的 ...

  5. go语言从例子开始之Example21.协程

    Go 协程 在执行上来说是轻量级的线程. golang使用协程用go关键字.后边正常调用函数. Example: package main import "fmt" func ak ...

  6. Python入门(一个有趣的画图例子实战)你肯定不会

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:qiu_fang  画一条可爱的python(蟒蛇): import t ...

  7. 一个简单的小例子让你明白c#中的委托-终于懂了!

    模拟主持人发布一个问题,由多个嘉宾来回答这个问题. 分析:从需求中抽出Host (主持人) 类和Guests (嘉宾) 类. 作为问题的发布者,Host不知道问题如何解答.因此它只能发布这个事件,将事 ...

  8. c++ 内存分配中一个有趣的小问题

    以下代码测试环境:vs2019 执行这么一段代码,看看会发生什么. int main() { ] = { }; arr[] = ; } 毫无疑问,会报错,因为访问越界了. 再看看另一段代码 ] = { ...

  9. 一个Java线程小例子(仿火车票售卖)

    public class MyThread extends Thread{ private static int ticket=100; public void run(){ for(int i=0; ...

随机推荐

  1. bzoj5281/luogu4377 Talent Show (01分数规划+背包dp)

    就是01分数规划的思路,只不过当把w[i]-r*t[i]>0的选完以后如果w值还没达到要求,那就再01背包dp一下就好了(dp时w值>W的时候就存在W里就不会爆内存了). (跑得很慢..大 ...

  2. 算法--java实现将数字转换成人民币大写(迅雷面试题)

    今天去迅雷面试,是个数字转换成人民币的算法题: public class Rmb { /** * 人民币的基本信息和操作 * * @author soyoungboy * @version 1.0 * ...

  3. 简单的使用gulp生成雪碧图

    有一个在线工具:https://www.toptal.com/developers/css/sprite-generator.生成雪碧图是极其方便的. 现在呢,我们来试试用gulp来生成雪碧图. 第一 ...

  4. Eclipse导入模板格式Xml配置文件

    Eclipse一般常用的可以导入两处 *.xml 格式的模板,一个是常用的注释格式模板,另一个是代码格式化时用的模板,导入方法如下: 假设: 1.xml 是代码注释格式模板     2.xml 是代码 ...

  5. circRNA

    一.circRNA序列提取 环状RNA (circRNA)是一类不具有 5' 末端帽子和 3' 末端 poly(A)尾巴.并以共价键形成环形结构的非编码 RNA 分子. 环状RNA (circRNA) ...

  6. xgboost应用

    在业务中,我们经常需要对数据建模并预测.简单的情况下,我们采用 if else 判断(一棵树)即可.但如果预测结果与众多因素有关,而每一个特征的权重又不尽相同. 所以我们如何把这些特征的权重合理的找出 ...

  7. vscode vue代码提示错误

    在用vscode编写vue代码时,因为安装的有vetur插件,所以当代码中有v-for语法时,会提示 [vue-language-server] 'v-for' directives require ...

  8. JAVA记录-java代码优化策略

    java代码优化策略 1.生成对象时,合理分配空间和大小:new ArrayList(100); 2.优化for循环: Vector vect = new Vector(1000); For(int ...

  9. Eclipse Groovy插件使用时出现的错误 org.eclipse.core.runtime.InvalidRegistryObjectException: Invalid registry object

    在eclipse marketplace中下载了groovy插件,发现使用的groovy版本跟项目中使用的groovy版本不一致. 于是在Preferences -> Groovy -> ...

  10. 05-迪米特法则(LOD 又名: 最少知道原则)

    1. 背景      类与类之间的关系越密切,耦合度越大,当一个类发生变化时,对另一个类的影响也越大. 2. 定义     一个类应该对其它类保持最少的了解. 3. 解决方法      尽量降低类与类 ...