Python3 has been launched for a long time, and there has been no time to learn about the coroutine features. This time I will follow the official documentation to learn about it.
Python version: 3.6.6
import asyncio
async def hello_world():print("Hello World!")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello_world())
loop.close()
There is actually no big difference from our normal execution of the function.
According to the official introduction, the coroutine here is done through a task, so here you need to define a loop
, this loop
will monitor the execution status of the incoming function. After the execution is complete, turn off this loop
.
In fact, Python3.8
has been changed to asyncio.run()
. This method is actually more user-friendly and basically does not perceive the implementation of coroutines.
import asyncio
async def slow_operation(future):await asyncio.sleep(1)
future.set_result('Future is done!')
loop = asyncio.get_event_loop()
future = asyncio.Future()
asyncio.ensure_future(slow_operation(future))
loop.run_until_complete(future)print(future.result())
loop.close()
As you can see, this is actually achieved by defining a Future
. After the asynchronous function is executed, the result is set by the set_result
method. You can get this result on the outer layer. In this way, you can write asynchronous programs with a synchronous mindset and get the returned results.
import asyncio
async def slow_operation():await asyncio.sleep(1)return'Future is done!'
def got_result(future):print(future.result())
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(slow_operation())
task.add_done_callback(got_result)
loop.run_until_complete(task)
loop.close()
The example here is modified by me with the official example, which is more convenient to understand. The callback here will be thrown into a Future
object. Get the result through the method of this object.
import asyncio
import time
async def factorial(name, number):
f =1for i inrange(2, number+1):print("Task %s: Compute factorial(%s)..."%(name, i))await asyncio.sleep(1)
f *= i
print("Task %s: factorial(%s) = %s"%(name, number, f))
loop = asyncio.get_event_loop()print(time.time())
loop.run_until_complete(asyncio.gather(factorial("A",2),factorial("B",2),factorial("C",2),))print(time.time())
loop.close()
A gather
method is introduced here. This method of isomorphism can perform multiple tasks at the same time.
I changed the official content of the above code. The execution result can be seen. These three tasks are actually performed simultaneously. The entire function execution time is only 1s. That is to achieve concurrency.
The example in the official document is actually to illustrate that the loop will wait for all tasks to complete before ending.
A task is automatically scheduled for execution when it is created. The event loop stops when all tasks are done.
While reading this content, I have been thinking about the difference between using time.sleep(1)
and await asyncio.sleep(1)
.
If you use await, the coroutine will switch context when it encounters this part. If await is not used, it will always block. This means that if await is not practical. . . Concurrency is a false proposition.
Change await asyncio.sleep(1)
in the above multitasking execution example to time.sleep(1)
. You will find that these three tasks are serial.
https://hackernoon.com/threaded-asynchronous-magic-and-how-to-wield-it-bba9ed602c32
https://docs.python.org/zh-cn/3.6/library/asyncio-task.html
Recommended Posts