繁体   English   中英

Python asyncio.semaphore in async-await function

[英]Python asyncio.semaphore in async-await function

我正在尝试自学 Python 的异步功能。 为此,我构建了一个异步 web 刮板。 我想限制我一次打开的连接总数,以便成为服务器上的好公民。 I know that semaphore's are a good solution, and the asyncio library has a semaphore class built in. My issue is that Python complains when using yield from in an async function as you are combining yield and await syntax. 以下是我正在使用的确切语法...

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. 使用线程。信号量? 这似乎可能会导致其他问题
  3. 出于这个原因,在 Python 3.6 的 beta 版中试试这个。

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

您可以使用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一个很好的入门asyncio

OK,所以这是真的很傻,但我只是取代了yield fromawait在信号灯上下文管理器,它是可以正常使用。

sema = asyncio.BoundedSemaphore(5)

async def get_page_text(url):
    with (await 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

用于信号量

sem = asyncio.Semaphore(10)

# ... later
async with sem:
    # work with shared resource

相当于

sem = asyncio.Semaphore(10)

# ... later
await sem.acquire()
try:
    # work with shared resource
finally:
    sem.release()

参考: https://docs.python.org/3/library/asyncio-sync.html#asyncio.Semaphore

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM