<p>一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python也是在python 3.4中引入了协程的概念。也通过这次整理更加深刻理解这个模块的使用</p>
<p><strong>asyncio 是干什么的?</strong></p>
<p><strong>异步网络操作并发协程</strong></p>
<p>python3.0时代,标准库里的异步网络模块:select(非常底层) python3.0时代,第三方异步网络库:Tornado python3.4时代,asyncio:支持TCP,子进程</p>
<p>现在的asyncio,有了很多的模块已经在支持:aiohttp,aiodns,aioredis等等 <a href="https://github.com/aio-libs" rel="external nofollow">https://github.com/aio-libs</a> 这里列出了已经支持的内容,并在持续更新</p>
<p>当然到目前为止实现协程的不仅仅只有asyncio,tornado和gevent都实现了类似功能</p>
<p>关于asyncio的一些关键字的说明:</p>
<p>event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数</p>
<p>coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。</p>
<p>task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态</p>
<p>future: 代表将来执行或没有执行的任务的结果。它和task上没有本质上的区别</p>
<p>async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。</p>
<p>看了上面这些关键字,你可能扭头就走了,其实一开始了解和研究asyncio这个模块有种抵触,自己也不知道为啥,这也导致很长一段时间,这个模块自己也基本就没有关注和使用,但是随着工作上用python遇到各种性能问题的时候,自己告诉自己还是要好好学习学习这个模块。</p>
<p>定义一个协程</p>
<div class="blockcode">
<pre class="brush:py;">
import time
import asyncio
now = lambda : time.time()
async def do_some_work(x):
print("waiting:", x)
start = now()
# 这里是一个协程对象,这个时候do_some_work函数并没有执行
coroutine = do_some_work(2)
print(coroutine)
# 创建一个事件loop
loop = asyncio.get_event_loop()
# 将协程加入到事件循环loop
loop.run_until_complete(coroutine)
print("Time:",now()-start)</pre>
</div>
<p>在上面带中我们通过async关键字定义一个协程(coroutine),当然协程不能直接运行,需要将协程加入到事件循环loop中</p>
<p>asyncio.get_event_loop:创建一个事件循环,然后使用run_until_complete将协程注册到事件循环,并启动事件循环</p>
<p><strong>创建一个task</strong></p>
<p>协程对象不能直接运行,在注册事件循环的时候,其实是run_until_complete方法将协程包装成为了一个任务(task)对象. task对象是Future类的子类,保存了协程运行后的状态,用于未来获取协程的结果</p>
<div class="blockcode">
<pre class="brush:py;">
import asyncio
import time
now = lambda: time.time()
async def do_some_work(x):
print("waiting:", x)
start = now()
coroutine = do_some_work(2)
loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
print(task)
loop.run_until_complete(task)
print(task)
print("Time:",now()-start)</pre>
</div>
<p>结果为:</p>
<div class="blockcode">
<pre class="brush:py;">
<Task pending coro=<do_some_work() running at /app/py_code/study_asyncio/simple_ex2.py:13>>
waiting: 2
<Task finished coro=<do_some_work() done, defined at /app/py_code/study_asyncio/simple_ex2.py:13> result=None>
Time: 0.0003514289855957031</pre>
</div>
<p>创建task后,在task加入事件循环之前为pending状态,当完成后,状态为finished</p>
<p>关于上面通过loop.create_task(coroutine)创建task,同样的可以通过 asyncio.ensure_future(coroutine)创建task</p>
<p>关于这两个命令的官网解释: <a href="https://docs.python.org/3/library/asyncio-task.html" rel="external nofollow">https://docs.python.org/3/library/asyncio-task.html</a></p>
<div class="blockcode">
<pre class="brush:py;">
asyncio.ensure_future(coro_or_future, *, loop=None)¶
Schedule the execution of a coroutine object: wrap it in a future. Return a Task object.
If the argument is a Future, it is returned directly.</pre>
</div>
<p><a href="https://docs.python.org/3/library/asyncio-eventloop.html" rel="external nofollow">https://docs.python.org/3/library/asyncio-eventloop.html</a></p>
<div class="blockcode">
<pre class="brush:py;">
AbstractEventLoop.create_task(coro)
Schedule the execution of a coroutine object: wrap it in a future. Return a Task object.
Third-party event loops can use their own subclass of Task for interoperability. In this case, the result type is a subclass of Task.
This method was added in Python 3.4.2. Use the async() function to support also older Python versions.</pre>
</div>
<p><strong>绑定回调</strong></p>
<p>绑定回调,在task执行完成的时候可以获取执行的结果,回调 |
|