A few asynchronous programming articles written earlier:
- Asynchronous Programming 101: What is Python Asyncio
- Asynchronous Programming 101: A Brief history of Python Async await development
- Asynchronous programming 101: Write an event loop
No more nonsense, on the code:
This code only works in Python3.7, since asyncio.run() was only introduced in Python3.7
import asyncio
async def heavy_task():
await asyncio.sleep(2)
async def main():
for _ in range(100):
await heavy_task()
if __name__ == '__main__':
asyncio.run(main())
Copy the code
How long will the above code take to complete? The answer is 20 seconds, not two seconds as we expected.
To understand why, you need to understand what await is doing: when an event loop executes to await, it suspends (suspends) the current coroutine, then looks at what other coroutines are in the current event loop pool that can be executed, and continues to execute the other coroutines.
The for loop in main() is a whole, and await heavy_task() suspends the whole main(), waits until the await heavy_task() is finished (in two seconds), and then returns to main(), continuing where it left off last time. And the last place I dropped it was inside this for loop.
So, is this program asynchronous? To be sure, yes, the whole program is asynchronous. But for main(), its for loop is still blocked.
The root of the problem is that we didn’t add coroutines to the event loop in time. The for loop will wait until heavy_Task () ends before creating the next coroutine. To solve this asyncio.gather() :
The code in the previous article creates all coroutines in advance and gives them to Asyncio.Gather () all at once.
import time
import asyncio
import aiohttp
async def fetch_async(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
status_code = resp.status
print(status_code)
async def visit_async():
start = time.time()
tasks = []
for _ in range(100):
tasks.append(fetch_async(URL))
await asyncio.gather(*tasks)
end = time.time()
print("visit_async tasks %.2f seconds" % (end - start))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(visit_async())
Copy the code
If you love computer science and basic logic like me, welcome to follow my wechat official account: