首页 > 编程 > Python > 正文

python并发2之使用asyncio处理并发

2020-02-16 11:14:43
字体:
来源:转载
供稿:网友

asyncio

在Python 2的时代,高性能的网络编程主要是使用Twisted、Tornado和Gevent这三个库,但是它们的异步代码相互之间既不兼容也不能移植。如上一节说的,Gvanrossum希望在Python 3 实现一个原生的基于生成器的协程库,其中直接内置了对异步IO的支持,这就是asyncio,它在Python 3.4被引入到标准库。

asyncio 这个包使用事件循环驱动的协程实现并发。

asyncio 包在引入标准库之前代号 “Tulip”(郁金香),所以在网上搜索资料时,会经常看到这种花的名字。

什么是事件循环?

wiki 上说:事件循环是”一种等待程序分配事件或者消息的编程架构“。基本上来说事件循环就是:”当A发生时,执行B"。或者用最简单的例子来解释这一概念就是每个浏览器中都存在的JavaScript事件循环。当你点击了某个东西(“当A发生时”),这一点击动作会发送给JavaScript的事件循环,并检查是否存在注册过的onclick 回调来处理这一点击(执行B)。只要有注册过的回调函数就会伴随点击动作的细节信息被执行。事件循环被认为是一种虚幻是因为它不停的手机事件并通过循环来发如何应对这些事件。

对 Python 来说,用来提供事件循环的 asyncio 被加入标准库中。asyncio 重点解决网络服务中的问题,事件循环在这里将来自套接字(socket)的 I/O 已经准备好读和/或写作为“当A发生时”(通过selectors模块)。除了 GUI 和 I/O,事件循环也经常用于在别的线程或子进程中执行代码,并将事件循环作为调节机制(例如,合作式多任务)。如果你恰好理解 Python 的 GIL,事件循环对于需要释放 GIL 的地方很有用。

线程与协程

我们先看两断代码,分别用 threading 模块和asyncio 包实现的一段代码。

# sinner_thread.pyimport threadingimport itertoolsimport timeimport sysclass Signal: # 这个类定义一个可变对象,用于从外部控制线程 go = Truedef spin(msg, signal): # 这个函数会在单独的线程中运行,signal 参数是前边定义的Signal类的实例 write, flush = sys.stdout.write, sys.stdout.flush for char in itertools.cycle('|/-//'): # itertools.cycle 函数从指定的序列中反复不断地生成元素  status = char + ' ' + msg  write(status)  flush()  write('/x08' * len(status)) # 使用退格符把光标移回行首  time.sleep(.1) # 每 0.1 秒刷新一次  if not signal.go: # 如果 go属性不是 True,退出循环   break write(' ' * len(status) + '/x08' * len(status)) # 使用空格清除状态消息,把光标移回开头def slow_function(): # 模拟耗时操作 # 假装等待I/O一段时间 time.sleep(3) # 调用sleep 会阻塞主线程,这么做事为了释放GIL,创建从属线程 return 42def supervisor(): # 这个函数设置从属线程,显示线程对象,运行耗时计算,最后杀死进程 signal = Signal() spinner = threading.Thread(target=spin,        args=('thinking!', signal)) print('spinner object:', spinner) # 显示线程对象 输出 spinner object: <Thread(Thread-1, initial)> spinner.start() # 启动从属进程 result = slow_function() # 运行slow_function 行数,阻塞主线程。同时丛书线程以动画形式旋转指针 signal.go = False spinner.join() # 等待spinner 线程结束 return resultdef main(): result = supervisor()  print('Answer', result)if __name__ == '__main__': main()            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表