asyncio 是python3增加的特性。不过backport到了2.7了。
python 2.7
python 3.7
REF:
一份详细的asyncio入门教程 有大量的例子
不同线程的事件循环
很多时候,我们的事件循环用于注册协程,而有的协程需要动态的添加到事件循环中。一个简单的方式就是使用多线程。当前线程创建一个事件循环,然后在新建一个线程,在新线程中启动事件循环。当前线程不会被block。
介绍aiohttp
如何真正运行一个协程呢?asyncio 提供了三种机制:
(1)asyncio.run() 函数,这是异步程序的主入口,相当于C语言中的main函数。
(2)用await等待协程,比如上例中的 await asyncio.sleep(1) 。再看下面的例子,我们定义了协程 say_delay() ,在main()协程中调用两次,第一次延迟1秒后打印“你好”,第二次延迟2秒后打印“猿人学”。这样我们通过 await 运行了两个协程。
从起止时间,多个协程是顺序执行的
(3)通过 asyncio.create_task() 函数并发运行作为 asyncio 任务(Task) 的多个协程。下面,我们用create_task()来修改上面的main()协程,从而让两个say_delay()协程并发运行
起止时间,多个协程是并发执行的
深入理解Python异步编程(上) 非常系统的介绍
simple example 简单明了
深入理解 python 异步 i/o 库 —— asyncio 分析的详细
对于操作耗时长,而且不属于 i/o 操作,没法交给 selector 去调度,此时我们需要自己 yield,让其他的 task 能有机会来使用我们唯一的线程。
一旦决定使用异步,则系统每一层都必须是异步,“开弓没有回头箭”。
A stack backtrace exmaple
concurrent works with eventlet
/lib/python3.7/site-packages/eventlet/green/thread.py(42)__thread_body() -> func(*args, **kwargs) /usr/lib/python3.7/threading.py(890)_bootstrap() -> self._bootstrap_inner() /lib/python3.7/site-packages/eventlet/green/thread.py(63)wrap_bootstrap_inner() -> bootstrap_inner() /usr/lib/python3.7/threading.py(926)_bootstrap_inner() -> self.run() /usr/lib/python3.7/threading.py(870)run() -> self._target(*self._args, **self._kwargs) /usr/lib/python3.7/concurrent/futures/thread.py(78)_worker() -> work_item = work_queue.get(block=True) > /usr/lib/python3.7/pdb.py(186)sigint_handler() -> def sigint_handler(self, signum, frame):
Python Thread lib: