Python asyncio 模块

Python 3.4
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。

asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

用asyncio实现Hello world代码如下:

import asyncio

@asyncio.coroutine
def hello():
    print("Hello world!")
    # 异步调用asyncio.sleep(1):
    r = yield from asyncio.sleep(1)
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行。

hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。

把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。

我们用Task封装两个coroutine试试:

import threading
import asyncio

@asyncio.coroutine
def hello():
    print(‘Hello world! (%s)‘ % threading.currentThread())
    yield from asyncio.sleep(1)
    print(‘Hello again! (%s)‘ % threading.currentThread())

loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
观察执行过程:

Hello world! (<_MainThread(MainThread, started 140735195337472)>)
Hello world! (<_MainThread(MainThread, started 140735195337472)>)
(暂停约1秒)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)
Hello again! (<_MainThread(MainThread, started 140735195337472)>)
由打印的当前线程名称可以看出,两个coroutine是由同一个线程并发执行的。

如果把asyncio.sleep()换成真正的IO操作,则多个coroutine就可以由一个线程并发执行。

参考:https://www.liaoxuefeng.com/wiki/1016959663602400/1017970488768640
python3.5

关于asyncio的一些关键字的说明:

event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数

coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态

future: 代表将来执行或没有执行的任务的结果。它和task上没有本质上的区别

async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。
import asyncio
import time

now = lambda :time.time()

async def do_some_work(x):
    print("waiting:",x)
    # await 后面就是调用耗时的操作
    await asyncio.sleep(x)
    return "Done after {}s".format(x)

start = now()

coroutine = do_some_work(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
loop.run_until_complete(task)

print("Task ret:", task.result())
print("Time:", now() - start)

参考:https://www.cnblogs.com/zhaof/p/8490045.html
Python3.7

传统的asyncio异步事件循环
在Python3.7以前的版本,调用异步函数前要先调用asyncio.get_event_loop()函数获取事件循环loop对象,然后通过不同的策略调用loop.run_forever()方法或者loop.run_until_complete()方法执行异步函数。一个典型的例子是这样的。

import asyncio
import random
import datetime

async def wait_and_echo(content):
    wait = random.randint(0, 10)
    print(f‘print {content} after {wait} seconds‘)
    await asyncio.sleep(wait)
    print(f‘{content} printed at {datetime.datetime.utcnow().strftime("%H:%M:%S ")}‘)

async def main():
    await asyncio.gather(*[wait_and_echo(x) for x in range(10)])

loop = asyncio.get_event_loop()
tasks = [wait_and_echo(x) for x in range(10)]
loop.run_until_complete(asyncio.gather(*tasks))
运行结果如:

print 0 after 9 seconds
print 1 after 0 seconds
print 2 after 7 seconds
print 3 after 2 seconds
print 4 after 8 seconds
print 5 after 3 seconds
print 6 after 2 seconds
print 7 after 9 seconds
print 8 after 1 seconds
print 9 after 1 seconds
1 printed at 05:15:26
8 printed at 05:15:27
9 printed at 05:15:27
6 printed at 05:15:28
3 printed at 05:15:28
5 printed at 05:15:29
2 printed at 05:15:33
4 printed at 05:15:34
0 printed at 05:15:35
7 printed at 05:15:35
使用asyncio.run()函数执行异步函数
asyncio.run()函数的官方文档是这样子的:

Signature: asyncio.run(main, *, debug=False)
Docstring:
Run a coroutine.

This function runs the passed coroutine, taking care of
managing the asyncio event loop and finalizing asynchronous
generators.

This function cannot be called when another asyncio event loop is
running in the same thread.

If debug is True, the event loop will be run in debug mode.

This function always creates a new event loop and closes it at the end.
It should be used as a main entry point for asyncio programs, and should
ideally only be called once.

Example:

    async def main():
        await asyncio.sleep(1)
        print(‘hello‘)

    asyncio.run(main())
File:      c:\users\pc\appdata\local\programs\python\python37\lib\asyncio\runners.py
Type:      function
使用Python3.7中的新APIasyncio.run(),上述例子可以改写为:

import asyncio
import random
import datetime

async def wait_and_echo(content):
    wait = random.randint(0, 10)
    print(f‘print {content} after {wait} seconds‘)
    await asyncio.sleep(wait)
    print(f‘{content} printed at {datetime.datetime.utcnow().strftime("%H:%M:%S ")}‘)

async def main():
    await asyncio.gather(*[wait_and_echo(x) for x in range(10)])

asyncio.run(main())
运行结果并没有差异。

  

原文地址:https://www.cnblogs.com/liuwei0824/p/10831633.html

时间: 2024-08-30 07:07:58

Python asyncio 模块的相关文章

Python标准模块--asyncio

1 模块简介 asyncio模块作为一个临时的库,在Python 3.4版本中加入.这意味着,asyncio模块可能做不到向后兼容甚至在后续的Python版本中被删除.根据Python官方文档,asyncio通过coroutines.sockets和其它资源上的多路复用IO访问.运行网络客户端和服务端以及其它相关的原始服务等提供了一种单线程并发应用的架构.本文并不能覆盖所有关于asyncio模块的技术点,但是你可以学到如何去使用这个模块,以及为什么它是有用的. 如果你在一些较老的Python版本

python协程--asyncio模块(基础并发测试)

在高并发的场景下,python提供了一个多线程的模块threading,但似乎这个模块并不近人如意,原因在于cpython本身的全局解析锁(GIL)问题,在一段时间片内实际上的执行是单线程的.同时还存在着资源争夺的问题.python3.4之后引入了基于生成器对象的协程概念.也就是asyncio模块.除了asyncio模块,python在高并发这一问题还提出了另外一些解决方案,例如tornado和gevent都实现了类似的功能.由此,在方案选择上提供了更多的可能性.以下是threading模块和a

Python之asyncio模块的使用

asyncio模块作用:构建协程并发应用的工具 python并发的三大内置模块,简单认识: 1.multiprocessing:多进程并发处理 2.threading模块:多线程并发处理 3.asyncio模块:协程并发处理  1.启动一个协程,任务无返回值,需要注意:async的使用 #!/usr/bin/env python # -*- coding: utf-8 -*- import asyncio # 开头定义async,表示要在协程运行,不定义的话,循环监听增加不了 async def

python:asyncio模块

asyncio是python 3.4引入的标准库,直接内置了对异步io的支持 asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO 用asyncio实现Hello world代码如下: import asyncio @asyncio.coroutine def hello(): print("Hello world!") # 异步调用asyncio.sleep(1):

python asyncio 协程使用 (一)

由于脚本需要在完成事件处理后N秒检查事件处理结果,当执行失败时再执行另一个事件处理. 想要最小化完成这个功能.同时在第一时间就将执行完毕的结果反馈给接口. 因此想到使用协程. 使用之前先翻阅了一下现有的文档.以及参考了其他人的代码. 先改写成如下的用例: 1 import asyncio 2 3 async def do_some_work(x): 4 try: 5 return "success" 6 finally: 7 print('it can test') 8 await a

python MultiProcessing模块进程间通信的解惑与回顾

这段时间沉迷MultiProcessing模块不能自拔,没办法,python的基础不太熟,因此就是在不断地遇到问题解决问题.之前学习asyncio模块学的一知半解,后来想起MultiProcessing模块更是一知半解,趁着暑假无聊就研究了一下,不得不说,这加深了自己对Python基础的掌握与理解...于是就有了这一系列<python标准库之MultiProcessing库的研究 (1)><python MultiProcessing标准库使用Queue通信的注意要点><py

用yield实现协程 和asyncio模块

用yield实现协程 #基于yield实现异步 import time def consumer(): '''任务1:接收数据,处理数据''' while True: x=yield def producer(): '''任务2:生产数据''' g=consumer() next(g) for i in range(10000000): g.send(i) producer() 使用yield from实现的协程 import datetime import heapq # 堆模块 import

python之模块ctypes

# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块ctypes import ctypes #ctypes是python的一个外部库,它提供了C兼容的数据类型,并允许调用函数C DLL. #注意事项: #就我个人目前而言,了解该库是提供与C语言数据类型兼容的接口作用即可,不需要深入了解.

python shutil模块总结

shutil.copyfile(src,dst)复制文件,如果存在会覆盖 copymode( src, dst)复制权限 copystat(src, dst)复制访问时间和修改时间和权限 copy(src, dst) 复制文件到一个目录 copy2(src, dst)在copy上的基础上再复制文件最后访问时间与修改时间也复制过来了,类似于cp –p的东西 rmtree(path[, ignore_errors[, onerror]])删除文件 move(src, dst)move文件 copyt