Use async IO when you can; use threading when you must
example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
importasyncioasyncdefcount():print("One")awaitasyncio.sleep(1)print("Two")asyncdefmain():awaitasyncio.gather(count(),count(),count())if__name__=="__main__":importtimes=time.perf_counter()asyncio.run(main())elapsed=time.perf_counter()-sprint(f"{__file__} executed in {elapsed:0.2f} seconds.")
importasyncioimporttimeasyncdefsay_after(delay,what):awaitasyncio.sleep(delay)print(what)asyncdefmain():print(f"started at {time.strftime('%X')}")awaitsay_after(1,'hello')awaitsay_after(2,'world')print(f"finished at {time.strftime('%X')}")asyncio.run(main())
输出为
started at 10:51:11
hello
world
finished at 10:51:14
importasyncioimporttimeasyncdefsay_after(delay,what):awaitasyncio.sleep(delay)print(what)asyncdefmain():task1=asyncio.create_task(say_after(1,'hello'))task2=asyncio.create_task(say_after(2,'world'))print(f"started at {time.strftime('%X')}")# Wait until both tasks are completed (should take# around 2 seconds.)awaittask1awaittask2print(f"finished at {time.strftime('%X')}")asyncio.run(main())
输出为
started at 10:52:50
hello
world
finished at 10:52:52
importasyncioimportrandomasyncdefmyCoroutine(id):process_time=random.randint(1,5)awaitasyncio.sleep(process_time)print("Coroutine: {}, has successfully completed after {} seconds".format(id,process_time))asyncdefmain():tasks=[]foriinrange(10):tasks.append(asyncio.ensure_future(myCoroutine(i)))awaitasyncio.gather(*tasks)loop=asyncio.get_event_loop()try:loop.run_until_complete(main())finally:loop.close()
Awaitables
可以使用 await 的三种对象: coroutines, Tasks, Futures.
coroutines
A coroutine is a specialized version of a Python generator function. A coroutine is a function that can suspend its execution before reaching return, and it can indirectly pass control to another coroutine for some time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
importasyncioasyncdefnested():return42asyncdefmain():# Nothing happens if we just call "nested()".# A coroutine object is created but not awaited,# so it *won't run at all*.nested()# Let's do it differently now and await it:print(awaitnested())# will print "42".asyncio.run(main())
Tasks
Tasks are used to schedule coroutines concurrently.
When a coroutine is wrapped into a Task with functions like asyncio.create_task() the coroutine is automatically scheduled to run soon:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
importasyncioasyncdefnested():return42asyncdefmain():# Schedule nested() to run soon concurrently# with "main()".task=asyncio.create_task(nested())# "task" can now be used to cancel "nested()", or# can simply be awaited to wait until it is complete:awaittaskasyncio.run(main())
Futures
1
2
3
4
5
6
7
8
asyncdefmain():awaitfunction_that_returns_a_future_object()# this is also valid:awaitasyncio.gather(function_that_returns_a_future_object(),some_python_coroutine())
uvloop
uvloop is a fast, drop-in replacement of the built-in asyncio event loop. uvloop is implemented in Cython and uses libuv under the hood.
To make asyncio use uvloop, you can install the uvloop event loop policy: