Home >Backend Development >Python Tutorial >Detailed explanation of how to use coroutine objects and Future objects in asyncio

Detailed explanation of how to use coroutine objects and Future objects in asyncio

高洛峰
高洛峰Original
2017-03-28 15:28:172924browse

asyncio is the standard library introduced in Python version 3.4, which has direct built-in support for asynchronous IO. asyncio's Programming model is a message loop. Today we will discuss in detail the coroutine and Future objects in asyncio

">

The relationship between coroutine and Future

It seems that both are the same, because the following syntax can be used to obtain results asynchronously,

result = await future
result = await coroutine
In fact, coroutine is a

generatorfunction, which can be received from the outside Parameters can also produce results. The advantage of using coroutine is that we can pause a function and then resume execution later, for example, when network operations are involved, the function can be stopped until the response arrives. During the time, we can switch to other tasks to continue execution.

And Future is more like a Promise object in

Javascript It is a placeholder whose value will be calculated in the future. . In the above example, when we are waiting for the network IO function to complete, the function will give us a container, and the Promise will fill the container when it is completed. After filling, we can use the Callback function to obtain it. Actual results.

Task object is a subclass of Future, which links coroutine and Future, and encapsulates coroutine into a Future object.

Generally, you will see two methods of starting tasks.

tasks = asyncio.gather(
  asyncio.ensure_future(func1()),
  asyncio.ensure_future(func2())
)
loop.run_until_complete(tasks)
and

tasks = [
  asyncio.ensure_future(func1()),
  asyncio.ensure_future(func2())
  ]
loop.run_until_complete(asyncio.wait(tasks))
ensure_future can encapsulate coroutines into Tasks. asyncio.gather encapsulates some Futures and coroutines into a Future.

asyncio.wait itself is a coroutine.

run_until_complete can receive either a Future object or a coroutine object,

BaseEventLoop.run_until_complete(future)
Run until the Future is done.
If the argument is a coroutine object, it is wrapped by ensure_future().
Return the Future's result, or raise its exception.
The correct

exit way of the Task task

is in the task loop of asyncio , if you use CTRL-C to exit, even if the exception is caught, the task in the Event Loop will report an error, and the following error will appear,

Task was destroyed but it is pending!

task: wait_
for=>

according to According to the official documentation, the Task object will be considered to have exited only in the following situations:

a result / exception are available, or that the future was canceled

Cancel of the Task object and its parent class Future is slightly different. When Task.cancel() is called, the corresponding coroutine will throw a CancelledError exception in the next round of the

event loop. Using Future.cancelled() does not return True immediately (used to indicate the end of the task). It is considered canceled only after the above exception is processed and the task ends.

So to end the task, you can use

for task in asyncio.Task.all_tasks():
  task.cancel()
to find all the tasks and cancel them.

But CTRL-C will also stop the event loop, so it is necessary to restart the event loop.

try:
  loop.run_until_complete(tasks)
except KeyboardInterrupt as e:
  for task in asyncio.Task.all_tasks():
    task.cancel()
  loop.run_forever() # restart loop
finally:
  loop.close()
It is necessary to catch exceptions in each Task. If you are not sure, you can use

asyncio.gather(..., return_exceptions=True)

Convert exceptions into normal results and return them.

The above is the detailed content of Detailed explanation of how to use coroutine objects and Future objects in asyncio. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn