私はPythonの非同期機能を自分自身に教えようとしています。そうするために、私は非同期Webスクレイパーを構築しました。サーバー上で善良な市民になるために、一度に開く接続の総数を制限したいと思います。セマフォが良い解決策であることを私は知っています、そしてasyncioライブラリには セマフォ クラスが組み込まれています。私の問題はPythonでyield from
を使用すると文句を言うことですasync
構文とyield
構文を組み合わせたときのawait
関数。以下は私が使用している正確な構文です...
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
私が考えることができるいくつかの可能な解決策...
@asyncio.coroutine
デコレータを使用するだけです私は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"))
ここ からの例。このページは、一般的にasyncio
およびaiohttp
の入門書としても適しています。
OK、これは本当にばかげていますが、セマフォコンテキストマネージャーでyield from
をawait
に置き換えるだけで、完全に機能しています。
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