Let's start with partial functions
If you need to reduce the number of parameters of a function, you can use the
- functools.partial()
[function 1]: the partial() function allows you to set a fixed value for one or more parameters to reduce the number of parameters to be called next.
[function 2]: partial() is used to fix some parameters and return a new callable object.
About the calling steps of a coroutine
The following is a brief introduction to the use of asyncio.
-
🌰 event_loop event loop: the program opens an infinite loop, and the programmer registers some functions on the event loop. When the satisfaction event occurs, the corresponding coroutine function is called.
-
🌰 Coroutine: a coroutine object, which refers to a function defined with the async keyword. Its call will not execute the function immediately, but will return a coroutine object. The process object needs to be registered in the event loop and called by the event loop.
-
🌰 Task task: a cooperation object is a function that can be suspended in the native, and the task is to further encapsulate the cooperation, including various states of the task.
-
🌰 Future object: represents the result of tasks executed or not executed in the future. There is no essential difference between it and task;
-
🌰 async/await keyword: python3.5 is used to define the keyword of the coordinator, async is used to define a coordinator, and await is used to suspend the blocking asynchronous calling interface.
Key points:
1. When we add async keyword to a function, or use asyncio.coroutine Decorator decoration, it will become an asynchronous function.
2. Each thread has an event loop, and the main thread calls asyncio.get_event_loop creates an event loop;
3. Encapsulate tasks as sets asyncio.gather(*args), which is then passed into the event loop;
4. To leave the asynchronous task to the run of this cycle_ until_ Complete method, the event loop will arrange the execution of the coroutine. As with the method name, the method waits for the asynchronous task to complete.
[note] it is not only asyncio that implements the collaboration, but tornado and gevent can implement similar functions.
Let's take a look at an example 🌰 :
async def test1(): print("1") async def test2(): print("2") a = test1() b = test2() try: a.send(None) # The send method can be called to execute the coroutine function except StopIteration as e: print(e.value) # A StopIteration exception will be thrown when the execution of the cooperation function ends, indicating that the execution of the cooperation function ends and the return value is in value pass try: b.send(None) # The send method can be called to execute the coroutine function except StopIteration: print(e.value) # A StopIteration exception will be thrown when the execution of the cooperation function ends, indicating that the execution of the cooperation function ends and the return value is in value pass --- //Output: 1 2
[explanation] the program first executes the test1 function, and then executes the test2 function after the execution of the test1 function. From the perspective of execution process, there is no difference between the current co function and common function, and no asynchronous function is implemented.
On blocking and await
[concept] the process object defined by async keyword can be suspended for the time-consuming operation by using await (it is an alternative to yield in the generator, but the local process function is not allowed), giving up the current control right. When a process encounters an await, the event loop will suspend the process and execute other processes until the other processes are also suspended or finished, and the next process will be executed.
import asyncio async def test1(): print("1") await asyncio.sleep(1) # asyncio.sleep(1) The returned object is also a process object print("2") async def test2(): print("3") print("4") a = test1() b = test2() try: a.send(None) # The send method can be called to execute the coroutine function except StopIteration: # A StopIteration exception will be thrown when the execution of the cooperation function ends, indicating that the execution of the cooperation function ends pass try: b.send(None) # The send method can be called to execute the coroutine function except StopIteration: pass --- //Output: 1 3 4
[explanation] the program first executes the test1 co program function. When it reaches await, the test1 function stops executing (blocking); then it starts executing the test2 co program function until the completion of test2. From the results, we can see that the test1 function is not finished (print("2") until the program runs
Modify the above code block to make the test1 function execute completely
import asyncio async def test1(): print("1") await test2() print("2") async def test2(): print("3") print("4") loop = asyncio.get_event_loop() loop.run_until_complete(test1()) --- //Output: 1 3 4 2
[event cycle method] asyncio.get_ event_ The loop method can create an event loop and then use run_until_complete registers the process with the event loop and starts the event loop.
[skill upgrade] using async, you can define a collaboration object. Using await, you can suspend a time-consuming operation. Just like the yield function in the generator, the function gives control. When a process encounters an await, the event loop will suspend the process and execute other processes until other processes are also suspended or completed, and then execute the next process. The purpose of the process is to asynchronize some time-consuming operations.
About task tasks
Because the process object cannot run directly, when registering the event loop, it is actually run_ until_ The complete method wraps the contract into a task object. The so-called task object is a subclass of the Future class, which saves the status of the running process and is used to obtain the results of the process in the Future. We can also define the cooperation object as task manually. The improvement code is as follows:
[modify the above code block again]
import asyncio async def test1(): print("1") await test2() print("2") async def test2(): print("3") print("4") loop = asyncio.get_event_loop() task = loop.create_task(test1()) loop.run_until_complete(task)
[Key review] as mentioned earlier, task object can save the running state of the cooperation function and obtain the return value of the cooperation function;
How to get task objects?
-
Callback function needs to be bound
-
Output directly after running the task task task
[promotion] if the send method is used to execute the function, the return value can be used by catching the stopiteration exception StopIteration.value obtain.
[for example]: 🌰
import asyncio async def test_one(): print("Zurich") await test_two() print("Alzacar") return "stop" async def test_two(): print("--") print("$$$") loop = asyncio.get_event_loop() task = asyncio.ensure_future(test_one()) loop.run_until_complete(task) print(task.result()) --- [Output]: Zurich Alzacar -- $$$
Using the future object
[explanation]: the future object has several statuses: pending, running, done, Cancelled. When creating the future, the task is pending. When the event loop is called and executed, it is running. When the call is finished, it is done. If you need to stop the event loop, you need to cancel the task first. You can use the asyncio.Task Gets the task of the event loop.
[procedure: about the use of future objects]
import asyncio import functools async def test1(): print("1") await test2() print("2") return "stop" async def test2(): print("3") print("4") def callback(param1,param2,future): print(param1,param2) print('Callback:',future.result()) loop = asyncio.get_event_loop() task = asyncio.ensure_future(test1()) task.add_done_callback(functools.partial(callback,"param1","param2"))# Bind callback function loop.run_until_complete(task)
[note] the result method of the future object can get the return value of the cooperation function and create the task. test1() is a collaboration object.
The future object in the callback function is the task object created.
[insert one more sentence]: if the callback function needs to accept multiple parameters, it can be imported by partial function.
[about the termination of cooperation]
How to stop executing the process?
Step 1: cancel the task first
Step 2: stop the loop event cycle.
import asyncio async def test1(): print("1") await asyncio.sleep(3) print("2") return "stop" tasks = [ asyncio.ensure_future(test1()), asyncio.ensure_future(test1()), asyncio.ensure_future(test1()), ] loop = asyncio.get_event_loop() try: loop.run_until_complete(asyncio.wait(tasks)) except KeyboardInterrupt as e: for task in asyncio.Task.all_tasks(): task.cancel() loop.stop() loop.run_forever() finally: loop.close()
Â
Â