├── README.md ├── asyncio-tut.ipynb ├── concurrency.ipynb ├── tut1.py └── tut2.py /README.md: -------------------------------------------------------------------------------- 1 | # concurrent-programming-in-python 2 | 3 | Tutorial on Concurrent Programming in Python 4 | 5 | - Part 1: [What is Concurrent Programming?](https://www.youtube.com/watch?v=y85G7GLYhYA) 6 | - Part 2: [Coroutines in Python (async/await)](https://www.youtube.com/watch?v=c6uoxhaenHg) 7 | - Part 3: [Introduction to asyncio](https://www.youtube.com/watch?v=Hh47pBRkhns) 8 | - Part 4: [Concurrent Execution using asyncio](https://www.youtube.com/watch?v=tmMqdrEzVRI) 9 | 10 | Watch complete playlist [here](https://www.youtube.com/playlist?list=PLyb_C2HpOQSBsygWeCYkJ7wjxXShIql43). 11 | -------------------------------------------------------------------------------- /asyncio-tut.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# asyncio\n", 8 | "\n", 9 | "> To write **concurrent**, **asynchronous**, and **cooperative** code in a sequential style.\n", 10 | "\n", 11 | "\n", 12 | "### Concurrency vs Parallelism\n", 13 | "\n", 14 | "\n", 15 | "\n", 16 | "### Asynchronous vs Synchronous\n", 17 | "\n", 18 | "\n", 19 | "\n", 20 | "### Cooperative vs preemptive\n", 21 | "\n", 22 | "\n", 23 | "\n", 24 | "> asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc." 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "## Coroutine\n", 32 | "\n", 33 | "> A function which can pause and resume its execution.\n", 34 | "\n", 35 | "\n", 36 | "\n", 37 | "\n", 38 | "### How to define a coroutine?\n", 39 | "\n", 40 | "```python\n", 41 | "async def main():\n", 42 | " ...\n", 43 | " ...\n", 44 | "```" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 5, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "async def main():\n", 54 | " print(\"Hello\")" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 6, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "data": { 64 | "text/plain": [ 65 | "" 66 | ] 67 | }, 68 | "execution_count": 6, 69 | "metadata": {}, 70 | "output_type": "execute_result" 71 | } 72 | ], 73 | "source": [ 74 | "main()" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "### How to pause execution of coroutine?\n", 82 | "\n", 83 | "```python\n", 84 | "async def main():\n", 85 | " await awaitable_object\n", 86 | " ...\n", 87 | " ...\n", 88 | "```\n", 89 | "\n", 90 | "> Awaitable objects are: **coroutines**, **Tasks**, and **Futures**.\n", 91 | "\n", 92 | "> **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.\n", 93 | "\n", 94 | "> A **Future** is a special low-level awaitable object that represents an eventual result of an asynchronous operation.\n" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "\n", 102 | "### How to block coroutine for ***x*** seconds?\n", 103 | "\n", 104 | "#### Using asyncio.sleep\n", 105 | "\n", 106 | "```python\n", 107 | "async def main():\n", 108 | " print(\"Indian\")\n", 109 | " await asyncio.sleep(3)\n", 110 | " print(\"Pythonista\")\n", 111 | "```\n", 112 | "\n", 113 | "> asyncio.sleep() always suspends the current task, allowing other tasks to run.\n" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "### How to execute coroutine?\n", 121 | "\n", 122 | "#### Using Event Loop\n", 123 | "\n", 124 | "> The **event loop** is the core of every asyncio application. It runs in a thread (typically the main thread) and executes all callbacks and Tasks in its thread.\n", 125 | "\n", 126 | "```python\n", 127 | "loop = asyncio.get_event_loop()\n", 128 | "loop.run_until_complete(my_coroutine())\n", 129 | "loop.close()\n", 130 | "```\n", 131 | "\n", 132 | "#### A shortcut... (since Python 3.7)\n", 133 | "\n", 134 | "```python\n", 135 | "asyncio.run(my_coroutine())\n", 136 | "```\n" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "### How to execute coroutines concurrently?\n", 144 | "\n", 145 | "#### Using asyncio.gather\n", 146 | "\n", 147 | "```python\n", 148 | "import asyncio\n", 149 | "\n", 150 | "async def main():\n", 151 | " await asyncio.gather(\n", 152 | " coro1(),\n", 153 | " coro2(),\n", 154 | " coro3()\n", 155 | " )\n", 156 | "\n", 157 | "asyncio.run(main())\n", 158 | "```" 159 | ] 160 | } 161 | ], 162 | "metadata": { 163 | "kernelspec": { 164 | "display_name": "pyenv37", 165 | "language": "python", 166 | "name": "pyenv37" 167 | }, 168 | "language_info": { 169 | "codemirror_mode": { 170 | "name": "ipython", 171 | "version": 3 172 | }, 173 | "file_extension": ".py", 174 | "mimetype": "text/x-python", 175 | "name": "python", 176 | "nbconvert_exporter": "python", 177 | "pygments_lexer": "ipython3", 178 | "version": "3.7.0" 179 | } 180 | }, 181 | "nbformat": 4, 182 | "nbformat_minor": 2 183 | } 184 | -------------------------------------------------------------------------------- /concurrency.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# What is concurrent?\n", 8 | "\n", 9 | "> Concurrent describes things that are occurring, or people who are doing something, **at the same time**, such as “concurrent users” of a computer program. \n", 10 | ">\n", 11 | ">On the other hand, Consecutive refers to things that are arranged or happen in a sequential order.\n", 12 | "\n", 13 | "### Real life example? \n", 14 | "\n", 15 | "> Sequential Engineering vs Concurrent Design and Manufacturing\n", 16 | "\n", 17 | "![](https://upload.wikimedia.org/wikipedia/commons/d/d6/Waterfall_vs_iterative.JPG)\n" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "# What is concurrent programming/computing?\n", 25 | "\n", 26 | "> In a concurrent program, several streams of operations may execute concurrently. Each stream of operations executes as it would in a sequential program except for the fact that streams can communicate and interfere with one another. \n", 27 | "\n", 28 | "> Concurrency is a property of a system which enables overlapping of process lifetimes.\n", 29 | "\n", 30 | "![](http://amrelroumy.github.io/2013/06/concurrent-execution.jpg)\n", 31 | "\n", 32 | "# Concurrency vs Parallelism\n", 33 | "\n", 34 | "\n" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "# A simple story...\n", 42 | "\n", 43 | "--------\n", 44 | "\n", 45 | "![](https://i.imgur.com/Pg2uuH2.png)\n", 46 | "\n", 47 | "------------\n", 48 | "\n", 49 | "![](https://i.imgur.com/uOqlK6P.png)\n", 50 | "\n", 51 | "----------\n", 52 | "\n", 53 | "![](https://i.imgur.com/nhgBpYN.png)" 54 | ] 55 | } 56 | ], 57 | "metadata": { 58 | "kernelspec": { 59 | "display_name": "Python 3", 60 | "language": "python", 61 | "name": "python3" 62 | }, 63 | "language_info": { 64 | "codemirror_mode": { 65 | "name": "ipython", 66 | "version": 3 67 | }, 68 | "file_extension": ".py", 69 | "mimetype": "text/x-python", 70 | "name": "python", 71 | "nbconvert_exporter": "python", 72 | "pygments_lexer": "ipython3", 73 | "version": "3.6.6" 74 | } 75 | }, 76 | "nbformat": 4, 77 | "nbformat_minor": 2 78 | } 79 | -------------------------------------------------------------------------------- /tut1.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def main(): 5 | print("Hello") 6 | await asyncio.sleep(2) 7 | print("World!") 8 | 9 | 10 | loop = asyncio.get_event_loop() 11 | loop.run_until_complete(main()) 12 | loop.close() 13 | 14 | # for python 3.7 15 | # asyncio.run(main()) 16 | 17 | -------------------------------------------------------------------------------- /tut2.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | 4 | 5 | async def display_time(): 6 | start_time = time.time() 7 | while True: 8 | dur = int(time.time() - start_time) 9 | if dur % 3 == 0: 10 | print("{} seconds have passed".format(dur)) 11 | await asyncio.sleep(1) 12 | 13 | 14 | async def print_nums(): 15 | num = 1 16 | while True: 17 | print(num) 18 | num += 1 19 | await asyncio.sleep(0.1) 20 | 21 | 22 | async def main(): 23 | task1 = asyncio.ensure_future(display_time()) 24 | task2 = asyncio.ensure_future(print_nums()) 25 | 26 | # for python 3.7 27 | # task1 = asyncio.create_task(display_time()) 28 | # task2 = asyncio.create_task(print_nums()) 29 | 30 | await asyncio.gather(task1, task2) 31 | 32 | 33 | loop = asyncio.get_event_loop() 34 | loop.run_until_complete(main()) 35 | loop.close() 36 | 37 | # for python 3.7 38 | # asyncio.run(main()) 39 | --------------------------------------------------------------------------------