├── 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 | "\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 | "\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 | "\n",
46 | "\n",
47 | "------------\n",
48 | "\n",
49 | "\n",
50 | "\n",
51 | "----------\n",
52 | "\n",
53 | ""
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 |
--------------------------------------------------------------------------------