python异步函数 python异步执行命令( 四 )


先来看一段代码 , 这个是我刚开始使用asyncawait语法时,写的一段小程序 。
#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time
async def wait_download(url):
response = await requets.get(url)
print("get {} response complete.".format(url))
async def main():
start = time.time()
await asyncio.wait([
wait_download(""),
wait_download(""),
wait_download("")])
end = time.time()
print("Complete in {} seconds".format(end - start))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())12345678910111213141516171819202122232425
这里会收到这样的报错:
Task exception was never retrieved
future: Task finished coro=wait_download() done, defined at asynctest.py:9 exception=TypeError("object Response can't be used in 'await' expression",)
Traceback (most recent call last):
File "asynctest.py", line 10, in wait_download
data = https://www.04ip.com/post/await requests.get(url)
TypeError: object Response can't be used in 'await' expression123456
这是由于requests.get()函数返回的Response对象不能用于await表达式,可是如果不能用于await,还怎么样来实现异步呢?
原来Python的await表达式是类似于”yield from”的东西,但是await会去做参数检查,它要求await表达式中的对象必须是awaitable的,那啥是awaitable呢? awaitable对象必须满足如下条件中其中之一:
1、A native coroutine object returned from a native coroutine function .
原生协程对象
2、A generator-based coroutine object returned from a function decorated with types.coroutine() .
types.coroutine()修饰的基于生成器的协程对象,注意不是Python3.4中asyncio.coroutine
3、An object with an await method returning an iterator.
实现了await method,并在其中返回了iterator的对象
根据这些条件定义,我们可以修改代码如下:
#!/usr/bin/env python# encoding:utf-8import asyncioimport requestsimport time
async def download(url): # 通过async def定义的函数是原生的协程对象
response = requests.get(url)
print(response.text)
async def wait_download(url):
await download(url) # 这里download(url)就是一个原生的协程对象
print("get {} data complete.".format(url))
async def main():
start = time.time()
await asyncio.wait([
wait_download(""),
wait_download(""),
wait_download("")])
end = time.time()
print("Complete in {} seconds".format(end - start))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())123456789101112131415161718192021222324252627282930
好了现在一个真正的实现了异步编程的小程序终于诞生了 。
而目前更牛逼的异步是使用uvloop或者pyuv,这两个最新的Python库都是libuv实现的,可以提供更加高效的event loop 。
uvloop和pyuv
pyuv实现了Python2.x和3.x,但是该项目在github上已经许久没有更新了,不知道是否还有人在维护 。
uvloop只实现了3.x, 但是该项目在github上始终活跃 。
它们的使用也非常简单,以uvloop为例,只需要添加以下代码就可以了
import asyncioimport uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())123
python2.7怎么实现异步改进之前
之前,我的查询步骤很简单,就是:
前端提交查询请求 -- 建立数据库连接 -- 新建游标 -- 执行命令 -- 接受结果 -- 关闭游标、连接
这几大步骤的顺序执行 。
这里面当然问题很大:
建立数据库连接实际上就是新建一个套接字 。这是进程间通信的几种方法里,开销最大的了 。
在“执行命令”和“接受结果”两个步骤中,线程在阻塞在数据库内部的运行过程中,数据库连接和游标都处于闲置状态 。

推荐阅读