私はapiからjsonsをダウンロードしていて、asyncioモジュールを使っています。すでに作成され、それが利用可能なダウンローダオブジェクトを持っているので、それぞれを呼び出すクラスのこのインスタンスメソッド、のように実装長いジョブでasyncio.ensure_futureを使用するのはなぜですか?
loop = asyncio.get_event_loop()
main_task = asyncio.ensure_future(klass.download_all())
loop.run_until_complete(main_task)
とdownload_all()
:このよう実装されている私の質問の核心は、次のイベントループで、ありますそれぞれのdownload
方法:
async def download_all(self):
""" Builds the coroutines, uses asyncio.wait, then sifts for those still pending, loops """
ret = []
async with aiohttp.ClientSession() as session:
pending = []
for downloader in self._downloaders:
pending.append(asyncio.ensure_future(downloader.download(session)))
while pending:
dne, pnding= await asyncio.wait(pending)
ret.extend([d.result() for d in dne])
# Get all the tasks, cannot use "pnding"
tasks = asyncio.Task.all_tasks()
pending = [tks for tks in tasks if not tks.done()]
# Exclude the one that we know hasn't ended yet (UGLY)
pending = [t for t in pending if not t._coro.__name__ == self.download_all.__name__]
return ret
なぜそれはダウンローダdownload
方法で、代わりにawait
構文で、私はasyncio.ensure_future
を行うことを選択したときに代わりに、それは仕方速く走る、それは 『非同期』としてより一見であること、です私はtから見ることができます彼は記録する。
これは、私が保留中のすべてのタスクを検出し、download_all
メソッドを完了させないように設定し、asyncio.wait
を呼び出し続けるために機能します。
await
キーワードは、イベントループ機構がそのことを行い、リソースを効率的に共有できると考えましたか?どのようにこのようにするのが速いのですか?何か問題がありますか?たとえば:
async def download(self, session):
async with session.request(self.method, self.url, params=self.params) as response:
response_json = await response.json()
# Not using await here, as I am "supposed" to
asyncio.ensure_future(self.write(response_json, self.path))
return response_json
async def write(self, res_json, path):
# using aiofiles to write, but it doesn't (seem to?) support direct json
# so converting to raw text first
txt_contents = json.dumps(res_json, **self.json_dumps_kwargs);
async with aiofiles.open(path, 'w') as f:
await f.write(txt_contents)
実装完全なコードと実際のAPIで、私は34秒で44のリソースをダウンロードすることができましたが、使用している場合、それはそう取っていたとして、私は実際にあきらめた(それが3分以上かかりました待ちます長いです)。