Skip to content

Commit 67f748f

Browse files
committed
Add futures and loop inspections.
1 parent da8f35b commit 67f748f

11 files changed

Lines changed: 106 additions & 28 deletions

File tree

asyncio_tutorial/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33

44
from asyncio_tutorial.logger import LOGGER
55

6-
from .part_I_asyncio_intro import intro_tutorial
6+
from .part_I_asyncio_intro import asyncio_intro_tutorial
77
from .part_II_aiohttp_aiofiles import aiohttp_aiofiles_tutorial
88

99

1010
def init_script():
11-
asyncio.run(intro_tutorial())
12-
LOGGER.info("-------------------------------------------")
11+
"""
12+
Run source code found in Hackersandslackers asyncio tutorials.
13+
14+
1. Intro to Async Python: https://hackersandslackers.com/python-concurrency-asyncio/
15+
2. Intro to Async Python: https://hackersandslackers.com/async-requests-with-aiohttp/
16+
"""
17+
asyncio.run(asyncio_intro_tutorial())
1318
asyncio.run(aiohttp_aiofiles_tutorial())

asyncio_tutorial/part_II_aiohttp_aiofiles/__init__.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,17 @@
77
from config import EXPORT_DIR, HTML_HEADERS
88
from data import urls
99

10+
from .futures import register_future
11+
from .loops import inspect_event_loop
1012
from .tasks import create_tasks
1113

1214

1315
async def aiohttp_aiofiles_tutorial():
1416
"""Open async HTTP session & execute created tasks."""
1517
LOGGER.info(f"Asyncio tutorial Part II: HTTP Requests with Aiohttp & Aiofiles.")
18+
future = register_future()
1619
async with ClientSession(headers=HTML_HEADERS) as session:
1720
tasks = await create_tasks(session, urls, EXPORT_DIR)
21+
inspect_event_loop()
1822
await asyncio.gather(*tasks)
19-
await inspect_loop()
20-
LOGGER.success(f"Saved {len(urls)} files to `{EXPORT_DIR}`")
21-
22-
23-
async def inspect_loop() -> str:
24-
"""
25-
Get event loop info.
26-
27-
:param: List[Task] tasks
28-
29-
:return: str
30-
"""
31-
loop = asyncio.get_event_loop()
32-
return LOGGER.info(f"Loop finished in {loop.time()} seconds.")
23+
future.set_result(f"Saved {len(urls)} files to `{EXPORT_DIR}`")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Create a Future (callback): an action to be taken when loop is completed."""
2+
import asyncio
3+
from asyncio import Future
4+
5+
from asyncio_tutorial.logger import LOGGER
6+
7+
8+
def register_future() -> Future:
9+
"""
10+
Create a Future to log when loop is completed.
11+
12+
:returns: Future
13+
"""
14+
loop = asyncio.get_event_loop()
15+
future = loop.create_future()
16+
future.add_done_callback(loop_completed)
17+
return future
18+
19+
20+
def loop_completed(result: str):
21+
"""
22+
Callback to be called when loop is complete.
23+
24+
:param str result: Simple string describing the state of the loop
25+
"""
26+
LOGGER.success(result)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import asyncio
2+
3+
from asyncio_tutorial.logger import LOGGER
4+
5+
6+
def inspect_event_loop():
7+
"""Get event loop info."""
8+
loop = asyncio.get_event_loop()
9+
thread_id = loop.__dict__.get("_thread_id")
10+
if loop.is_running():
11+
LOGGER.info(
12+
f"Loop has been running {loop.time()} seconds. (Thread ID #{thread_id})"
13+
)

asyncio_tutorial/part_I_asyncio_intro/__init__.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
from asyncio_tutorial.logger import LOGGER
55

66
from .coroutines import simple_coroutine
7+
from .futures import register_future
8+
from .loops import inspect_event_loop
79
from .tasks import create_task
810

911

10-
async def intro_tutorial():
12+
async def asyncio_intro_tutorial():
1113
"""Simple demonstration of a async script lifecycle"""
1214
LOGGER.info(f"Asyncio tutorial Part I: Intro to Asyncio.")
1315
tasks = []
16+
future = register_future()
1417
for i in range(3):
1518
task = await create_task(simple_coroutine(i, delay=1))
1619
tasks.append(task)
17-
LOGGER.info(type(task))
20+
inspect_event_loop()
1821
await asyncio.gather(*tasks)
19-
LOGGER.info("-------------------------------------------")
22+
future.set_result("Done")

asyncio_tutorial/part_I_asyncio_intro/coroutines.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
async def simple_coroutine(number: int, delay=1):
88
"""
9-
Wait for a period of time before logging the coro number.
9+
Wait for a time delay, log number associated with the coroutine.
1010
1111
:param int number: Number to identify the current coroutine.
1212
:param int delay: Time delay to simulate a function which takes time to complete.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Create a Future (callback): an action to be taken when loop is completed."""
2+
import asyncio
3+
from asyncio import Future
4+
5+
from asyncio_tutorial.logger import LOGGER
6+
7+
8+
def register_future() -> Future:
9+
"""
10+
Create a Future to log when loop is completed.
11+
12+
:returns: Future
13+
"""
14+
loop = asyncio.get_event_loop()
15+
future = loop.create_future()
16+
future.add_done_callback(loop_completed)
17+
return future
18+
19+
20+
def loop_completed(result: str):
21+
"""
22+
Callback to be called when loop is complete.
23+
24+
:param str result: Simple string describing the state of the loop
25+
"""
26+
LOGGER.success(
27+
f"Loop completed with result: {result} \
28+
\n-------------------------------------------------"
29+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import asyncio
2+
3+
from asyncio_tutorial.logger import LOGGER
4+
5+
6+
def inspect_event_loop():
7+
"""Get event loop info."""
8+
loop = asyncio.get_event_loop()
9+
thread_id = loop.__dict__.get("_thread_id")
10+
if loop.is_running():
11+
LOGGER.info(
12+
f"Loop has been running {loop.time()} seconds. (Thread ID #{thread_id})"
13+
)

asyncio_tutorial/part_I_asyncio_intro/tasks.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import asyncio
33
from asyncio import Task
44

5-
from asyncio_tutorial.logger import LOGGER
6-
75

86
async def create_task(coroutine) -> Task:
97
"""
@@ -13,5 +11,4 @@ async def create_task(coroutine) -> Task:
1311
1412
:returns: Task
1513
"""
16-
LOGGER.info(type(coroutine))
1714
return asyncio.create_task(coroutine)

data/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Parse data from local files."""
2-
from .parser import parse_urls
32
from config import CSV_FILEPATH
43

4+
from .parser import parse_urls
55

6-
urls = parse_urls(CSV_FILEPATH)
6+
urls = parse_urls(CSV_FILEPATH)

0 commit comments

Comments
 (0)