Python 3.5 async/await with real code example

后端 未结 2 1661
情话喂你
情话喂你 2021-01-30 14:00

I\'ve read tons of articles and tutorial about Python\'s 3.5 async/await thing. I have to say I\'m pretty confused, because some use get_event_loop() and run_until_complete(), s

相关标签:
2条回答
  • 2021-01-30 14:41

    You can take a look at the following simple working example from here. By the way it returns a string worth reading :-)

    import aiohttp
    import asyncio
    
    async def fetch(client):
      async with client.get('https://docs.aiohttp.org/en/stable/client_reference.html') as resp:
        assert resp.status == 200
        return await resp.text()
    
    async def main():
      async with aiohttp.ClientSession() as client:
        html = await fetch(client)
        print(html)
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    
    0 讨论(0)
  • 2021-01-30 14:54

    If a third-party library is not compatible with async/await then obviously you can't use it easily. There are two cases:

    1. Let's say that the function in the library is asynchronous and it gives you a callback, e.g.

      def fn(..., clb):
          ...
      

      So you can do:

      def on_result(...):
          ...
      
      fn(..., on_result)
      

      In that case you can wrap such functions into the asyncio protocol like this:

      from asyncio import Future
      
      def wrapper(...):
          future = Future()
          def my_clb(...):
              future.set_result(xyz)
          fn(..., my_clb)
          return future
      

      (use future.set_exception(exc) on exception)

      Then you can simply call that wrapper in some async function with await:

      value = await wrapper(...)
      

      Note that await works with any Future object. You don't have to declare wrapper as async.

    2. If the function in the library is synchronous then you can run it in a separate thread (probably you would use some thread pool for that). The whole code may look like this:

      import asyncio
      import time
      from concurrent.futures import ThreadPoolExecutor
      
      # Initialize 10 threads
      THREAD_POOL = ThreadPoolExecutor(10)
      
      def synchronous_handler(param1, ...):
          # Do something synchronous
          time.sleep(2)
          return "foo"
      
      # Somewhere else
      async def main():
          loop = asyncio.get_event_loop()
          futures = [
              loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...),
              loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...),
              loop.run_in_executor(THREAD_POOL, synchronous_handler, param1, ...),
          ]
          await asyncio.wait(futures)
          for future in futures:
              print(future.result())
      
      with THREAD_POOL:
          loop = asyncio.get_event_loop()
          loop.run_until_complete(main())
      

    If you can't use threads for whatever reason then using such a library simply makes entire asynchronous code pointless.

    Note however that using synchronous library with async is probably a bad idea. You won't get much and yet you complicate the code a lot.

    0 讨论(0)
提交回复
热议问题