2016-12-23 1 views
0

私は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分以上かかりました待ちます長いです)。

答えて

0

forループごとにawaitを実行すると、すべての繰り返しがダウンロードされます。
一方、ensure_futureを実行すると、すべてのファイルをダウンロードするタスクが作成されず、すべてのファイルが2番目のループで待機します。

関連する問題