Slide 1

Slide 1 text

Asynchronous Python for the Complete Beginner Miguel Grinberg @miguelgrinberg

Slide 2

Slide 2 text

S**t Programmers Say... Async makes your code go fast!

Slide 3

Slide 3 text

The simplest definition of Async... “A style of concurrent programming”

Slide 4

Slide 4 text

How Does Python Do Multiple Things At Once?

Slide 5

Slide 5 text

Multiple Processes ● The OS does all the multi-tasking work ● Only option for multi-core concurrency

Slide 6

Slide 6 text

Multiple Threads ● The OS does all the multi-tasking work ● In CPython, the GIL prevents multi-core concurrency

Slide 7

Slide 7 text

Asynchronous Programming ● No OS intervention ● One process, one thread What’s the trick?

Slide 8

Slide 8 text

Synchronous Chess Exhibition ● Assumptions: - 24 opponents - Polgár moves in 5 seconds - Opponents move in 55 seconds - Games average 30 move pairs ● Each game runs for 30 minutes ● 24 sequential games would take 24 x 30 min = 720 min = 12 hours!!! Photo by Ed Yourdon Simultaneous chess exhibition by Judit Polgár, 1992

Slide 9

Slide 9 text

Asynchronous Chess Exhibition ● Polgár moves on first game ● While opponent thinks, she moves on second game, then third, fourth... ● A move on all 24 games takes her 24 x 5 sec = 120 sec = 2 min ● After she completes the round, the first game is ready for her next move! ● 24 games are completed in 2 min x 30 = 60 min = 1 hour! Photo by Ed Yourdon Simultaneous chess exhibition by Judit Polgár, 1992

Slide 10

Slide 10 text

A practical definition of Async... “A style of concurrent programming in which tasks release the CPU during waiting periods, so that other tasks can use it.”

Slide 11

Slide 11 text

How is Async Implemented?

Slide 12

Slide 12 text

Suspend and Resume ● Async functions need the ability to suspend and resume ● A function that enters a waiting period is suspended, and only resumed when the wait is over ● Four ways to implement suspend/resume in Python: - Callback functions - Generator functions - Async/await (Python 3.5+) - Greenlets (requires greenlet package)

Slide 13

Slide 13 text

Scheduling Asynchronous Tasks ● Async frameworks need a scheduler, usually called “event loop” ● The loop keeps track of all the running tasks ● When a function is suspended, return controls to the loop, which then finds another function to start or resume ● This is called “cooperative multi-tasking”

Slide 14

Slide 14 text

Examples See them on GitHub: https://bit.ly/asyncpython

Slide 15

Slide 15 text

from time import sleep def hello(): print('Hello') sleep(3) print('World!') if __name__ == '__main__': hello() Example: Standard (synchronous) Python Print “hello”, wait three seconds, then print “world”

Slide 16

Slide 16 text

Example: Asyncio Print “hello”, wait three seconds, then print “world” import asyncio loop = asyncio.get_event_loop() @asyncio.coroutine def hello(): print('Hello') yield from asyncio.sleep(3) print('World!') if __name__ == '__main__': loop.run_until_complete(hello()) import asyncio loop = asyncio.get_event_loop() async def hello(): print('Hello') await asyncio.sleep(3) print('World!') if __name__ == '__main__': loop.run_until_complete(hello())

Slide 17

Slide 17 text

Example: Greenlet Frameworks Print “hello”, wait three seconds, then print “world” from gevent import sleep def hello(): print('Hello') sleep(3) print('World!') if __name__ == '__main__': hello() from eventlet import sleep def hello(): print('Hello') sleep(3) print('World!') if __name__ == '__main__': hello()

Slide 18

Slide 18 text

Async Pitfalls

Slide 19

Slide 19 text

CPU Heavy Tasks ● Long CPU-intensive tasks must routinely release the CPU to avoid starving other tasks ● This can be done by “sleeping” periodically, such as once per loop iteration ● To tell the loop to return control back as soon as possible, sleep for 0 seconds ● Example: await asyncio.sleep(0)

Slide 20

Slide 20 text

Async and the Python Standard Library ● Blocking library functions are incompatible with async frameworks socket.*, select.* subprocess.*, os.waitpid threading.*, multiprocessing.* time.sleep ● All async frameworks provide non-blocking replacements for these ● Eventlet and Gevent can “monkey-patch” the standard library to make it async compatible

Slide 21

Slide 21 text

Conclusion

Slide 22

Slide 22 text

Processes vs. Threads vs. Async Processes Threads Async Optimize waiting periods Yes (preemptive) Yes (preemptive) Yes (cooperative) Use all CPU cores Yes No No Scalability Low (ones/tens) Medium (hundreds) High (thousands+) Use blocking std library functions Yes Yes No GIL interference No Some No

Slide 23

Slide 23 text

Thank You! Miguel Grinberg @miguelgrinberg