“与...同步”在Python 3.4中
aiohttp入门文档给出了以下客户端示例:
The Getting Started docs for aiohttp give the following client example:
import asyncio
import aiohttp
async def fetch_page(session, url):
with aiohttp.Timeout(10):
async with session.get(url) as response:
assert response.status == 200
return await response.read()
loop = asyncio.get_event_loop()
with aiohttp.ClientSession(loop=loop) as session:
content = loop.run_until_complete(
fetch_page(session, 'http://python.org'))
print(content)
他们为Python 3.4用户提供以下注释:
And they give the following note for Python 3.4 users:
如果您使用的是Python 3.4,请使用@coroutine装饰器将await替换为from和
异步def。
If you are using Python 3.4, please replace await with yield from and async def with a @coroutine decorator.
如果我按照以下说明进行操作,则会得到:
If I follow these instructions I get:
import aiohttp
import asyncio
@asyncio.coroutine
def fetch(session, url):
with aiohttp.Timeout(10):
async with session.get(url) as response:
return (yield from response.text())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
with aiohttp.ClientSession(loop=loop) as session:
html = loop.run_until_complete(
fetch(session, 'http://python.org'))
print(html)
但是,它不会运行,因为Python 3.4不支持与
异步:
However, this will not run, because async with
is not supported in Python 3.4:
$ python3 client.py
File "client.py", line 7
async with session.get(url) as response:
^
SyntaxError: invalid syntax
如何翻译 async与
语句配合使用Python 3.4吗?
How can I translate the async with
statement to work with Python 3.4?
仅不要使用 session.get()作为上下文管理器;直接将其用作协程。 session.get()
生成的请求上下文管理器通常会 释放退出时的请求,但使用 response.text()
也是如此,因此您可以在此处忽略它:
Just don't use the result of session.get()
as a context manager; use it as a coroutine directly instead. The request context manager that session.get()
produces would normally release the request on exit, but so does using response.text()
, so you could ignore that here:
@asyncio.coroutine
def fetch(session, url):
with aiohttp.Timeout(10):
response = yield from session.get(url)
return (yield from response.text())
请求返回的包装器没有必需的异步方法( __ aenter __
和 __ aexit __
),当不使用Python时,它们会完全省略3.5(请参见相关源代码)。
The request wrapper returned here doesn't have the required asynchronous methods (__aenter__
and __aexit__
), they omitted entirely when not using Python 3.5 (see the relevant source code).
如果在 session.get()
调用与访问 response.text之间有更多语句()
,您可能想使用 try:.. finally:
释放连接;如果发生异常,Python 3.5发布上下文管理器还会关闭响应。因为这里需要从response.release()中获得收益,所以不能在Python 3.4之前将其封装在上下文管理器中:
If you have more statements between the session.get()
call and accessing the response.text()
awaitable, you probably want to use a try:..finally:
anyway to release the connection; the Python 3.5 release context manager also closes the response if an exception occurred. Because a yield from response.release()
is needed here, this can't be encapsulated in a context manager before Python 3.4:
import sys
@asyncio.coroutine
def fetch(session, url):
with aiohttp.Timeout(10):
response = yield from session.get(url)
try:
# other statements
return (yield from response.text())
finally:
if sys.exc_info()[0] is not None:
# on exceptions, close the connection altogether
response.close()
else:
yield from response.release()