异步等待函数中的 Python asyncio.semaphore

新手上路,请多包涵

我正在尝试自学 Python 的异步功能。为此,我构建了一个异步网络抓取工具。我想限制我一次打开的连接总数,以成为服务器上的好公民。我知道信号量是一个很好的解决方案,并且 asyncio 库有一个内置的 信号量 类。我的问题是 Python 在使用 yield from 时会抱怨 async 功能,因为你正在组合 yieldawait 语法。以下是我正在使用的确切语法……

 import asyncio
import aiohttp

sema = asyncio.BoundedSemaphore(5)

async def get_page_text(url):
    with (yield from sema):
        try:
            resp = await aiohttp.request('GET', url)
            if resp.status == 200:
                ret_val = await resp.text()
        except:
            raise ValueError
        finally:
            await resp.release()
    return ret_val

引发此异常:

 File "<ipython-input-3-9b9bdb963407>", line 14
    with (yield from sema):
         ^
SyntaxError: 'yield from' inside async function

我能想到的一些可能的解决方案……

  1. 只需使用 @asyncio.coroutine 装饰器
  2. 使用threading.Semaphore?这似乎可能会导致其他问题
  3. 出于 这个 原因,请在 Python 3.6 的测试版中尝试这个。

我对 Python 的异步功能还很陌生,所以我可能会遗漏一些明显的东西。

原文由 Bruce Pucci 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 610
1 个回答

您可以使用 async with 语句来获取异步上下文管理器:

 #!/usr/local/bin/python3.5
import asyncio
from aiohttp import ClientSession

sema = asyncio.BoundedSemaphore(5)

async def hello(url):
    async with ClientSession() as session:
        async with sema, session.get(url) as response:
            response = await response.read()
            print(response)

loop = asyncio.get_event_loop()
loop.run_until_complete(hello("http://httpbin.org/headers"))

取自 此处 的示例。该页面也是 asyncioaiohttp 的入门读物。

原文由 Sebastian Wozny 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题