python的异步编程
2017-12-20 15:28
36 查看
这里的异步编程基于python3.4和python3.5
1、一些重要的概念理解
(1)循环消息队列:
异步IO采用消息循环的模式,重复“读取消息—处理消息”的过程
消息模型解决等待IO操作的问题:
程序发出IO请求,直接结束本轮消息处理,进入下一轮消息的处理
当IO操作完成守,将收到一条IO完成的消息,处理该消息时获取IO操作的结果
在IO操作的这段时间里,异步模型可以循环处理其他操作,而且没有线程切换的消耗,同时处理多个IO请求,适用于大多数IO密集型的应用程序
总结; "异步IO模型"需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程。
(2)协程——coroutine
协程,又称微线程,纤程。英文名Coroutine。协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。
协程调用与函数调用的区别:
协程调用:但执行过程中,在子程序(即函数)内部可中断,然后转而执行别的子程序(另一个函数),在适当的时候再返回 来接着执行。
协程针对的是一个线程中的函数调用之间,所以没有线程切换,是在一个线程中轮流执行和终端多个函数而已,所 以效率较高,而且不需要锁机制(只有一个线程执行)
需要注意的是,子程序内部中断的不是函数调用,而是被调用函数中断(一般来说可能是一条执行命令需要很长时 间等待结果返回,比如常见的IO操作),转而去执行另一个函数(不是调用另一个函数),类似两个函数轮流执 行,没有发生函数调用。
函数调用:程序执行中,函数调用是通过函数栈实现,因为栈FILO的特点,通常函数调用过程都是:A调用B,B在执行过程中 又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。子程序(函数)调用总是一个入口,一次返 回,调用顺序是明确的。而协程的调用和子程序不同
总结:协程的本质就是一个子程序,即一个使用async关键字定义的函数(在python3.4中使用的是@async.corontine修饰的函 数),它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用
(3)、事件循环
python异步IO的核心就在于事件循环,事件循环是一个无限的循环,程序开启一个无限的循环,程序员会把一些协程函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。即协程函数不是自己调用的,而是通过“事件循环”去掉用的。
操作如下:
loop = asyncio.get_event_loop() #获取“事件循环”对象
loop.run_until_complete(hello()) #通过事件循环,去调用协程函数
loop.close()
(4)、任务task
协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。即多个coroutine函数可以封装成一组Task然后并发执行,所谓task对象是Future类的子类。保存了协程运行后的状态,用于未来获取协程的结果。任务一般是有多个协程函数的时候,将他们绑定到一个任务组上,可以如下操作:
实际上即使没有使用任务task,当传入一个协程,其内部会自动封装成task,如下:
loop.run_until_complete(hello())
#程序也会自动将hello封装成一个task任务,若函数有参数,一定要传入参数哦
下面是几种创建任务的方法:
方法1:通过loop.create_task()创建任务
t=[loop.create_task(number_sub(10))] #因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错
loop.run_until_complete(asyncio.wait(t))
loop.close()
与下面的等价
t=loop.create_task(number_sub(10)) #因为不是列表的形式,所以不需要asyncio.wait,而直接将t作为参数,否则会报错
loop.run_until_complete(t)
loop.close()
方法2:通过 asyncio.ensure_future()创建任务
t=[asyncio.ensure_future(number_sub(10))]
#因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错
loop.run_until_complete(asyncio.wait(t))
loop.close()
与下面等价
t=asyncio.ensure_future(number_sub(10))
#因为不是列表的形式,所以不需要asyncio.wait,而直接将t作为参数,否则会报错
loop.run_until_complete(t)
loop.close()
方法3:一次将多个协程函数绑定到同一个任务——要写成任务列表的形式
#t=[asyncio.ensure_future(number_sub(10)),asyncio.ensure_future(character_list())] #方法一
#t=[loop.create_task(number_sub(10)),loop.create_task(character_list())] #方法二
t=[number_sub(10),character_list()] #方法三,这三种方法都可以
loop.run_until_complete(asyncio.wait(t)) #但因为是列表形式,所以要用wait
loop.close()
与下面是等价的
t=asyncio.gather(asyncio.ensure_future(number_sub(5)), asyncio.ensure_future(character_list()))
print(t)
loop.run_until_complete(t) #通过asyncio的gather()方法将多个协程函数连接起来,而没有写成列表形式,故而不需要wait()
print(t)
loop.close()
task进一步了解:
task也是一个对象,我们还可以通过打印task,来来查看相关的一些状态信息,如下所示:
loop=asyncio.get_event_loop()
t=loop.create_task(number_sub(10))
print(t) #执行之前的状态
loop.run_until_complete(t)
print(t)
loop.close()
打印结果如下 :
<Task pending coro=<number_sub() running at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3>>
it's 10
it's 9
it's 8
it's 7
it's 6
it's 5
it's 4
it's 3
it's 2
it's 1
<Task finished coro=<number_sub() done, defined at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3> result=None>
第一个表示执行之前的状态,然后执行出结果,第二个表示执行之后的状态。乱码是因为文件路径中出现了中文的缘故。
task是Future的子类。isinstance(task,
asyncio.Future)将会输出True。
下面是整个程序的代码:
import asyncio
@asyncio.coroutine #在python3.5里面,改为了async def number_sub(n):
def
number_sub(n):
while n>0:
print("it's
{0}".format(n))
yield from asyncio.sleep(1)
#asyncio.sleep()本身就是一个“异步协程函数” 当然这里可以是其他自定义的异步协程函数,
#这里仅仅是模拟一个耗时的异步过程
n-=1
#在python3.5里面,改为了await asyncio.sleep(1)
@asyncio.coroutine
#在python3.5里面,改为了async def number_sub(n):
def
character_list():
li=['a','b','c','d','e','f','g']
for i in li:
print("it's
{0}".format(i))
yield from asyncio.sleep(1)
#在python3.5里面,改为了await asyncio.sleep(1)
loop=asyncio.get_event_loop()
t=asyncio.gather(asyncio.ensure_future(number_sub(5)), asyncio.ensure_future(character_list()))
loop.run_until_complete(t)
loop.close()
在python3.5版本中,在语法层面在3.4的基础之上做了一些改进,即所谓的async——await语法。详情可以自己查阅相关的资料。
1、一些重要的概念理解
(1)循环消息队列:
异步IO采用消息循环的模式,重复“读取消息—处理消息”的过程
消息模型解决等待IO操作的问题:
程序发出IO请求,直接结束本轮消息处理,进入下一轮消息的处理
当IO操作完成守,将收到一条IO完成的消息,处理该消息时获取IO操作的结果
在IO操作的这段时间里,异步模型可以循环处理其他操作,而且没有线程切换的消耗,同时处理多个IO请求,适用于大多数IO密集型的应用程序
总结; "异步IO模型"需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程。
(2)协程——coroutine
协程,又称微线程,纤程。英文名Coroutine。协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。
协程调用与函数调用的区别:
协程调用:但执行过程中,在子程序(即函数)内部可中断,然后转而执行别的子程序(另一个函数),在适当的时候再返回 来接着执行。
协程针对的是一个线程中的函数调用之间,所以没有线程切换,是在一个线程中轮流执行和终端多个函数而已,所 以效率较高,而且不需要锁机制(只有一个线程执行)
需要注意的是,子程序内部中断的不是函数调用,而是被调用函数中断(一般来说可能是一条执行命令需要很长时 间等待结果返回,比如常见的IO操作),转而去执行另一个函数(不是调用另一个函数),类似两个函数轮流执 行,没有发生函数调用。
函数调用:程序执行中,函数调用是通过函数栈实现,因为栈FILO的特点,通常函数调用过程都是:A调用B,B在执行过程中 又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。子程序(函数)调用总是一个入口,一次返 回,调用顺序是明确的。而协程的调用和子程序不同
总结:协程的本质就是一个子程序,即一个使用async关键字定义的函数(在python3.4中使用的是@async.corontine修饰的函 数),它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用
(3)、事件循环
python异步IO的核心就在于事件循环,事件循环是一个无限的循环,程序开启一个无限的循环,程序员会把一些协程函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。即协程函数不是自己调用的,而是通过“事件循环”去掉用的。
操作如下:
loop = asyncio.get_event_loop() #获取“事件循环”对象
loop.run_until_complete(hello()) #通过事件循环,去调用协程函数
loop.close()
(4)、任务task
协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。即多个coroutine函数可以封装成一组Task然后并发执行,所谓task对象是Future类的子类。保存了协程运行后的状态,用于未来获取协程的结果。任务一般是有多个协程函数的时候,将他们绑定到一个任务组上,可以如下操作:
loop = asyncio.get_event_loop() tasks = [hello(), hello1(),hello2(),hello3()] #多个协程函数绑定到一个任务上面,记住多个任务需要将任务写成 列表的形式 loop.run_until_complete(asyncio.wait(tasks)) #当任务是列表的时候,必须使用asyncio.wait(t)的形式才行 loop.close()
实际上即使没有使用任务task,当传入一个协程,其内部会自动封装成task,如下:
loop.run_until_complete(hello())
#程序也会自动将hello封装成一个task任务,若函数有参数,一定要传入参数哦
下面是几种创建任务的方法:
方法1:通过loop.create_task()创建任务
t=[loop.create_task(number_sub(10))] #因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错
loop.run_until_complete(asyncio.wait(t))
loop.close()
与下面的等价
t=loop.create_task(number_sub(10)) #因为不是列表的形式,所以不需要asyncio.wait,而直接将t作为参数,否则会报错
loop.run_until_complete(t)
loop.close()
方法2:通过 asyncio.ensure_future()创建任务
t=[asyncio.ensure_future(number_sub(10))]
#因为是列表的形式,所以下面必须要用asyncio.wait(t)作为参数,否则会报错
loop.run_until_complete(asyncio.wait(t))
loop.close()
与下面等价
t=asyncio.ensure_future(number_sub(10))
#因为不是列表的形式,所以不需要asyncio.wait,而直接将t作为参数,否则会报错
loop.run_until_complete(t)
loop.close()
方法3:一次将多个协程函数绑定到同一个任务——要写成任务列表的形式
#t=[asyncio.ensure_future(number_sub(10)),asyncio.ensure_future(character_list())] #方法一
#t=[loop.create_task(number_sub(10)),loop.create_task(character_list())] #方法二
t=[number_sub(10),character_list()] #方法三,这三种方法都可以
loop.run_until_complete(asyncio.wait(t)) #但因为是列表形式,所以要用wait
loop.close()
与下面是等价的
t=asyncio.gather(asyncio.ensure_future(number_sub(5)), asyncio.ensure_future(character_list()))
print(t)
loop.run_until_complete(t) #通过asyncio的gather()方法将多个协程函数连接起来,而没有写成列表形式,故而不需要wait()
print(t)
loop.close()
task进一步了解:
task也是一个对象,我们还可以通过打印task,来来查看相关的一些状态信息,如下所示:
loop=asyncio.get_event_loop()
t=loop.create_task(number_sub(10))
print(t) #执行之前的状态
loop.run_until_complete(t)
print(t)
loop.close()
打印结果如下 :
<Task pending coro=<number_sub() running at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3>>
it's 10
it's 9
it's 8
it's 7
it's 6
it's 5
it's 4
it's 3
it's 2
it's 1
<Task finished coro=<number_sub() done, defined at f:\�о������꼶��\Tensorflow���ѧϰ\TensorFlowBoardʵ��\asyncio_3.4.py:3> result=None>
第一个表示执行之前的状态,然后执行出结果,第二个表示执行之后的状态。乱码是因为文件路径中出现了中文的缘故。
task是Future的子类。isinstance(task,
asyncio.Future)将会输出True。
下面是整个程序的代码:
import asyncio
@asyncio.coroutine #在python3.5里面,改为了async def number_sub(n):
def
number_sub(n):
while n>0:
print("it's
{0}".format(n))
yield from asyncio.sleep(1)
#asyncio.sleep()本身就是一个“异步协程函数” 当然这里可以是其他自定义的异步协程函数,
#这里仅仅是模拟一个耗时的异步过程
n-=1
#在python3.5里面,改为了await asyncio.sleep(1)
@asyncio.coroutine
#在python3.5里面,改为了async def number_sub(n):
def
character_list():
li=['a','b','c','d','e','f','g']
for i in li:
print("it's
{0}".format(i))
yield from asyncio.sleep(1)
#在python3.5里面,改为了await asyncio.sleep(1)
loop=asyncio.get_event_loop()
t=asyncio.gather(asyncio.ensure_future(number_sub(5)), asyncio.ensure_future(character_list()))
loop.run_until_complete(t)
loop.close()
在python3.5版本中,在语法层面在3.4的基础之上做了一些改进,即所谓的async——await语法。详情可以自己查阅相关的资料。
相关文章推荐
- python——asyncio模块实现协程、异步编程(一)
- Atitit.异步编程 java .net php python js 的比较
- Python3 异步编程之进程与线程-1
- [Python]深入理解 Python 异步编程(上)
- python——asyncio模块实现协程、异步编程(二)
- 利用python yielding创建协程将异步编程同步化
- Atitit.异步编程 java .net php python js 的比较
- Python的Twisted框架上手前所必须了解的异步编程思想
- 异步编程设计模式 - IronPythonDebugger
- 用 Python 3 的 async / await 做异步编程
- 最新Python异步编程详解
- Atitit.异步编程 java .net php python js 对照
- Python的Tornado框架异步编程入门实例
- Python Twisted网络编程框架与异步编程入门教程
- Python 异步编程 asyncio
- Python/Twisted 异步编程教程
- Python中的协程和异步编程
- 理解 Python 中的异步编程
- 用 Python 3 的 async / await 做异步编程
- 利用 Python yield 创建协程将异步编程同步化