For better presentation, I prepared three functions, a synchronization function, two asynchronous functions
#Define blocking function DEF the ping (url): Print ( "blocking function starts running") the time.sleep (2) os.system ( "the ping% S"% url) Print ( "end of run blocking function") #define two asynchronous functions the async DEF asyncfunc1 (): Print ( "the Suspending func1") the await asyncio.sleep (. 1) Print ( "FUNC func1", threading.current_thread ()) Print ( 'Resuming func1') return "func1" the async DEF asyncfunc2 (): Print ( "the Suspending func2") the await asyncio.sleep (. 1) Print ( "FUNC func2", threading.current_thread ()) Print ( 'Resuming func2') return "func2"
Control task coroutine
Run a single task coroutine
The above function, for example, I just want to asyncfunc1 () function runs and get the results, you can use the loop.create_task()
method to create a task object, task Futures is a subclass when calling loop.run_until_complete()
later after coroutine finish, by task.result()
acquiring coroutine function return result.
async def asyncfunc1(): print("Suspending func1") await asyncio.sleep(1) print("func func1 ", threading.current_thread()) print('Resuming func1') return "func1" if __name__=="__main__": print("In main thread ",threading.current_thread()) loop = asyncio.get_event_loop() task = loop.create_task(asyncfunc1()) loop.run_until_complete(task) print("task result is ",task.result())
The output is
In main thread <_mainthread(mainthread, started="" 6140)=""> Suspending func1 func func1 <_mainthread(mainthread, started="" 6140)=""> Resuming func1 task result is func1
And the main thread is running coroutine function in the same thread.
You can also add a callback method to task objects
#coding:gbk import asyncio import time,sys async def asyncfunc1(): print("Suspending func1") await asyncio.sleep(1) print("func func1 ", threading.current_thread()) print('Resuming func1') return "func1" # 定义一个回调函数 def callbackfunc(task): print("task 运行结束,它的结果是:",task.result()) if __name__=="__main__": print("In main thread ",threading.current_thread()) loop = asyncio.get_event_loop() task = loop.create_task(asyncfunc1()) task.add_done_callback(callbackfunc) loop.run_until_complete(task)
The output is
In main thread<_mainthread(mainthread, started="" 11248)="">
Suspending func1
func func1<_mainthread(mainthread, started="" 11248)="">
Resuming func1
Run the end of the task, its results are: func1
loop.run_until_complete
Is a blocking method, after ending only when it is inside the coroutine runs until the end of this method, the code will run after.
In fact, you can not call loop.run_until_complete
after method, create a task, in fact, has been in the running coroutine function, but when the event loop if ready to start running, and this time the task state pending
, if not call the event loop, then do not run coroutine function, since the main thread finish, the sub-thread will be destroyed, such as code written as:
if __name__=="__main__": print("In main thread ",threading.current_thread()) loop = asyncio.get_event_loop() task = loop.create_task(asyncfunc1()) time.sleep(3)
The resulting output is
In main thread<_mainthread(mainthread, started="" 6056)="">
Task was destroyed but it is pending!
task:
cb=[callbackfunc() at test.py:39]>
sys:1: RuntimeWarning: coroutine ‘asyncfunc1’ was never awaited
So you want to make coroutine function is implemented, you need to call the event loop to perform tasks above loop.run_until_complete
it is to make the cycle began to run, in fact, can also use loop.run_forever()
this function as its name suggests, will always run. Only the event loop run up, then use the cycle registered coroutine will be implemented, but if loop.run_forever()
it will back up here, there is a event loop stop
method, the end of the cycle, we can add a callback method on the object task when after the end of the coroutine execution, calling the event loop stop
way to end the whole cycle
#coding:gbk import asyncio import time,sys async def asyncfunc1(): print("Suspending func1") await asyncio.sleep(1) print("func func1 ", threading.current_thread()) print('Resuming func1') return "func1" # 定义一个回调函数 def callbackfunc(task): print("task 运行结束,它的结果是:",task.result()) loop.stop() if __name__=="__main__": print("In main thread ",threading.current_thread()) loop = asyncio.get_event_loop() task = loop.create_task(asyncfunc1()) task.add_done_callback(callbackfunc) loop.run_forever()
In addition to using loop.run_until_complete
the method, may also be used asyncio.ensure_future()
a method coroutine to run the code above task = loop.create_task(asyncfunc1())
to task = asyncio.ensure_future(asyncfunc1())
get the same result, it is coroutine object or parameter futures, task object may be passed as a futures subclass task, when incoming is a coroutine object, and returns a task object, passing a futures when the futures returns the object directly, that is to say, in the call asyncio.ensure_future()
later, will return a task object that it can add a callback method and can be called task.result () method to get the result (note that if the task is not performed end result is called method will throw an exception).
A plurality of tasks in parallel coroutine
I've got the top two asynchronous functions asyncfunc1 and asyncfunc2, if I want to perform these two functions simultaneously and get their return values that how does it work?
With the experience of a single coroutine above, we can also use the event to create two task cycle, then () is executed in run_forever, you can add a callback to the task, and outputs the result.
#coding: GBK Import ASYNCIO # define two asynchronous functions the async DEF asyncfunc1 (): Print ( "the Suspending func1") the await asyncio.sleep (. 1) Print ( "FUNC func1", threading.current_thread ()) Print ( 'Resuming func1 ') return "func1" the async DEF asyncfunc2 (): Print ( "the Suspending func2") the await asyncio.sleep (. 1) Print ( "FUNC func2", threading.current_thread ()) Print (' Resuming func2 ') return "func2" # define a callback function DEF callbackfunc (task): Print ( "the end of the task run, it is the result:", task.result ()) IF __name__ __ == "__ main__": Print ( "In main thread ",threading.current_thread()) Loop = ASYNCIO.get_event_loop() task1 = loop.create_task(asyncfunc1()) task1.add_done_callback(callbackfunc) task2 = loop.create_task(asyncfunc2()) task2.add_done_callback(callbackfunc) loop.run_forever()
The output is
In main thread<_mainthread(mainthread, started="" 8040)="">
Suspending func1
Suspending func2
func func1<_mainthread(mainthread, started="" 8040)="">
Resuming func1
func func2<_mainthread(mainthread, started="" 8040)="">
Resuming func2
Run the end of the task, its results are: func1
Run the end of the task, its results are: func2
This time due to loop called run_forever method, and there is no way to call the stop method, so the program will have the card.
Such a process may be a plurality of co-run, but such a process complicated one, the second is not convenient to recover the result.
asyncio gather there is a method that may be passed multiple task objects, when calling await asyncio.gather (*), it will return all the results
Due to await only write in async def function, so there is also a need to create a new function
async def main(): task1 = loop.create_task(asyncfunc1()) task1.add_done_callback(callbackfunc) task2 = loop.create_task(asyncfunc2()) task2.add_done_callback(callbackfunc) result = await asyncio.gather(task1,task2) print(result) async def mian2(): result = await asyncio.gather(asyncfunc1(),asyncfunc2()) print(result)
Both definitions are ways, one is to gather transfer function is coroutine object is passed to a task object. After calling
if __name__=="__main__": print("In main thread ",threading.current_thread()) loop = asyncio.get_event_loop() loop.run_until_complete(main()) # or main2()
The resulting output is
In main thread<_mainthread(mainthread, started="" 7016)="">
Suspending func1
Suspending func2
func func1<_mainthread(mainthread, started="" 7016)="">
Resuming func1
func func2<_mainthread(mainthread, started="" 7016)="">
Resuming func2
Run the end of the task, its results are: func1
Run the end of the task, its results are: func2
[‘func1’, ‘func2’]
This achieves a parallel coroutine recovery and outcome.
This article briefly introduced here, then will continue to analyze the implementation of the synchronization code.