asynciodemo/asyncio.ipynb

311 lines
7.1 KiB
Plaintext
Executable File

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Asyncio"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Asyncio is an asynchronous IO library for Python that utilises the async/await syntax . I was added to the standard library in Python 3.5. \n",
"\n",
"This is a simple over view. Asyncio and async/await isn't the the simplest, this is my take on it.\n",
"\n",
"There is more in-depth content in the Further Reading section bellow"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Synchronous vs Asynchronous"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are two ways of running code, synchronously; multiple tasks sequentially and asynchronously; multiple tasks concurrently."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Sync delay"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"\n",
"def syncsleep(delay):\n",
" print(\"Sleeping for {} seconds\".format(str(delay)))\n",
" time.sleep(delay)\n",
" print(\"Finished sleeping for {} seconds\".format(str(delay)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"syncsleep(2)\n",
"syncsleep(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Async delay"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"\n",
"async def asyncsleep(delay):\n",
" print(\"Sleeping for {} seconds\".format(str(delay)))\n",
" await asyncio.sleep(delay)\n",
" print(\"Finished sleeping for {} seconds\".format(str(delay)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"loop = asyncio.get_event_loop() \n",
"loop.create_task(asyncsleep(3))\n",
"loop.create_task(asyncsleep(2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What is it good for?\n",
"\n",
"Asyncio is good for IO bound code, including file and network IO.\n",
"\n",
"It is not good for CPU bound tasks, like mathematical computations or tightly bound loops.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Async Await"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Async and await are basicly fancy generators that we call coroutines. Coroutines are functions that can be paused, like generators. ```await``` is basicly the same as ```yeild from```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generators"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fib(limit): \n",
" a, b = 0, 1\n",
" \n",
" while a < limit: \n",
" yield a \n",
" a, b = b, a + b \n",
" return \"Done\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f = fib(10)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"f.__next__()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for i in fib(5): \n",
" print(i) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Event loop\n",
"\n",
"A coroutine can only called and awited by another coroutine. This causes a chicken and egg problem. \n",
"\n",
"To solve this problem an event loop is needed. Asyncio is an implemetation of an event loop. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## How it works\n",
"\n",
"Asyncio runs in a single thread, it uses cooperative mulitasking.\n",
"\n",
"A coroutine will pause while it waits for a result, giving controll back to the event loop. This allows other coroutines to run. \n",
"\n",
"When a result is received the event loop will pick it up and continue execution of the coroutine. \n",
"\n",
"Because a coroutine pauses and releases controll, data corruption isn't a problem like it is with threading."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Async Libraries\n",
"Functions used with asyncio need to be coroutines, awaitable, non-blocking. This causes a problem as most libraries aren't. Aiolibs is a collection of libraries that are. \n",
"\n",
"https://github.com/aio-libs\n",
"\n",
"There is a collection of libraries including, aiohttp; http client and server, aio{database}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Aiohttp\n",
"https://github.com/aio-libs/aiohttp"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import aiohttp\n",
"import asyncio\n",
"\n",
"async def main():\n",
" async with aiohttp.ClientSession() as session:\n",
" async with session.get('http://localhost:8080') as resp:\n",
" print(resp.status)\n",
" print(await resp.text())\n",
"\n",
"\n",
"await main()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"from aiofile import async_open\n",
"\n",
"\n",
"async def main():\n",
" async with async_open(\"hello.txt\", 'w+') as afp:\n",
" await afp.write(\"Hello \")\n",
" await afp.write(\"world\")\n",
" afp.seek(0)\n",
"\n",
" print(await afp.read())\n",
"\n",
" \n",
"loop = asyncio.get_event_loop()\n",
"loop.create_task(main())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Curio\n",
"https://curio.readthedocs.io/en/latest/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sources and Further Reading\n",
"\n",
"https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work/51116910#51116910\n",
"\n",
"https://realpython.com/async-io-python/\n",
"\n",
"https://realpython.com/python-concurrency/\n",
"\n",
"https://github.com/MagicStack/uvloop\n",
"\n",
"https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/\n",
"\n",
"https://www.geeksforgeeks.org/generators-in-python/\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}