Skip to content

Commit 9e16069

Browse files
authored
Merge branch 'master' into python-mixins
2 parents fb71447 + 1625a07 commit 9e16069

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+851
-38
lines changed

python-asyncio/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Python's `asyncio`: A Hands-On Walkthrough
2+
3+
This folder provides the code examples for the Real Python tutorial [Python's `asyncio`: A Hands-On Walkthrough](https://realpython.com/async-io-python/).

python-asyncio/as_completed.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import asyncio
2+
import time
3+
4+
5+
async def main():
6+
task1 = asyncio.create_task(coro([10, 5, 2]))
7+
task2 = asyncio.create_task(coro([3, 2, 1]))
8+
print("Start:", time.strftime("%X"))
9+
for task in asyncio.as_completed([task1, task2]):
10+
result = await task
11+
print(f'result: {result} completed at {time.strftime("%X")}')
12+
print("End:", time.strftime("%X"))
13+
print(f"Both tasks done: {all((task1.done(), task2.done()))}")
14+
15+
16+
async def coro(numbers):
17+
await asyncio.sleep(min(numbers))
18+
return list(reversed(numbers))
19+
20+
21+
if __name__ == "__main__":
22+
asyncio.run(main())

python-asyncio/chained.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import asyncio
2+
import random
3+
import time
4+
5+
6+
async def main():
7+
user_ids = [1, 2, 3]
8+
start = time.perf_counter()
9+
await asyncio.gather(
10+
*(get_user_with_posts(user_id) for user_id in user_ids)
11+
)
12+
end = time.perf_counter()
13+
print(f"\n==> Total time: {end - start:.2f} seconds")
14+
15+
16+
async def get_user_with_posts(user_id):
17+
user = await fetch_user(user_id)
18+
await fetch_posts(user)
19+
20+
21+
async def fetch_user(user_id):
22+
delay = random.uniform(0.5, 2.0)
23+
print(f"User coro: fetching user by {user_id=}...")
24+
await asyncio.sleep(delay)
25+
user = {"id": user_id, "name": f"User{user_id}"}
26+
print(f"User coro: fetched user with {user_id=} (done in {delay:.1f}s).")
27+
return user
28+
29+
30+
async def fetch_posts(user):
31+
delay = random.uniform(0.5, 2.0)
32+
print(f"Post coro: retrieving posts for {user['name']}...")
33+
await asyncio.sleep(delay)
34+
posts = [f"Post {i} by {user['name']}" for i in range(1, 3)]
35+
print(
36+
f"Post coro: got {len(posts)} posts by {user['name']}"
37+
f" (done in {delay:.1f}s):"
38+
)
39+
for post in posts:
40+
print(f" - {post}")
41+
42+
43+
if __name__ == "__main__":
44+
random.seed(444)
45+
asyncio.run(main())

python-asyncio/countasync.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import asyncio
2+
3+
4+
async def main():
5+
await asyncio.gather(count(), count(), count())
6+
7+
8+
async def count():
9+
print("One")
10+
await asyncio.sleep(1)
11+
print("Two")
12+
await asyncio.sleep(1)
13+
14+
15+
if __name__ == "__main__":
16+
import time
17+
18+
start = time.perf_counter()
19+
asyncio.run(main())
20+
elapsed = time.perf_counter() - start
21+
print(f"{__file__} executed in {elapsed:0.2f} seconds.")

python-asyncio/countsync.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import time
2+
3+
4+
def main():
5+
for _ in range(3):
6+
count()
7+
8+
9+
def count():
10+
print("One")
11+
time.sleep(1)
12+
print("Two")
13+
time.sleep(1)
14+
15+
16+
if __name__ == "__main__":
17+
start = time.perf_counter()
18+
main()
19+
elapsed = time.perf_counter() - start
20+
print(f"{__file__} executed in {elapsed:0.2f} seconds.")

python-asyncio/except_group.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import asyncio
2+
3+
4+
async def main():
5+
results = await asyncio.gather(
6+
coro_a(), coro_b(), coro_c(), return_exceptions=True
7+
)
8+
exceptions = [e for e in results if isinstance(e, Exception)]
9+
if exceptions:
10+
raise ExceptionGroup("Errors", exceptions)
11+
12+
13+
async def coro_a():
14+
await asyncio.sleep(1)
15+
raise ValueError("Error in coro A")
16+
17+
18+
async def coro_b():
19+
await asyncio.sleep(2)
20+
raise TypeError("Error in coro B")
21+
22+
23+
async def coro_c():
24+
await asyncio.sleep(0.5)
25+
raise IndexError("Error in coro C")
26+
27+
28+
if __name__ == "__main__":
29+
try:
30+
asyncio.run(main())
31+
except* ValueError as ve_group:
32+
print(f"[ValueError handled] {ve_group.exceptions}")
33+
except* TypeError as te_group:
34+
print(f"[TypeError handled] {te_group.exceptions}")
35+
except* IndexError as ie_group:
36+
print(f"[IndexError handled] {ie_group.exceptions}")

python-asyncio/gathers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import asyncio
2+
import time
3+
4+
5+
async def main():
6+
task1 = asyncio.create_task(coro([10, 5, 2]))
7+
task2 = asyncio.create_task(coro([3, 2, 1]))
8+
print("Start:", time.strftime("%X"))
9+
result = await asyncio.gather(task1, task2)
10+
print("End:", time.strftime("%X"))
11+
print(f"Both tasks done: {all((task1.done(), task2.done()))}")
12+
return result
13+
14+
15+
async def coro(numbers):
16+
await asyncio.sleep(min(numbers))
17+
return list(reversed(numbers))
18+
19+
20+
if __name__ == "__main__":
21+
result = asyncio.run(main())
22+
print(f"result: {result}")

python-asyncio/powers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import asyncio
2+
3+
4+
async def main():
5+
g = []
6+
async for i in powers_of_two(5):
7+
g.append(i)
8+
print(g)
9+
f = [j async for j in powers_of_two(5) if not (j // 3 % 5)]
10+
print(f)
11+
12+
13+
async def powers_of_two(stop=10):
14+
exponent = 0
15+
while exponent < stop:
16+
yield 2**exponent
17+
exponent += 1
18+
await asyncio.sleep(0.2) # Simulate some asynchronous work
19+
20+
21+
if __name__ == "__main__":
22+
asyncio.run(main())

python-asyncio/queued.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import asyncio
2+
import random
3+
import time
4+
5+
6+
async def main():
7+
queue = asyncio.Queue()
8+
user_ids = [1, 2, 3]
9+
10+
start = time.perf_counter()
11+
await asyncio.gather(
12+
producer(queue, user_ids),
13+
*(consumer(queue) for _ in user_ids),
14+
)
15+
end = time.perf_counter()
16+
print(f"\n==> Total time: {end - start:.2f} seconds")
17+
18+
19+
async def producer(queue, user_ids):
20+
async def fetch_user(user_id):
21+
delay = random.uniform(0.5, 2.0)
22+
print(f"Producer: fetching user by {user_id=}...")
23+
await asyncio.sleep(delay)
24+
user = {"id": user_id, "name": f"User{user_id}"}
25+
print(f"Producer: fetched user with {user_id=} (done in {delay:.1f}s)")
26+
await queue.put(user)
27+
28+
await asyncio.gather(*(fetch_user(uid) for uid in user_ids))
29+
for _ in range(len(user_ids)):
30+
await queue.put(None) # Sentinels for consumers to terminate
31+
32+
33+
async def consumer(queue):
34+
while True:
35+
user = await queue.get()
36+
if user is None:
37+
break
38+
delay = random.uniform(0.5, 2.0)
39+
print(f"Consumer: retrieving posts for {user['name']}...")
40+
await asyncio.sleep(delay)
41+
posts = [f"Post {i} by {user['name']}" for i in range(1, 3)]
42+
print(
43+
f"Consumer: got {len(posts)} posts by {user['name']}"
44+
f" (done in {delay:.1f}s):"
45+
)
46+
for post in posts:
47+
print(f" - {post}")
48+
49+
50+
if __name__ == "__main__":
51+
random.seed(444)
52+
asyncio.run(main())

python-asyncio/rand.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import asyncio
2+
import random
3+
4+
COLORS = (
5+
"\033[0m", # End of color
6+
"\033[36m", # Cyan
7+
"\033[91m", # Red
8+
"\033[35m", # Magenta
9+
)
10+
11+
12+
async def main():
13+
return await asyncio.gather(
14+
makerandom(1, 9),
15+
makerandom(2, 8),
16+
makerandom(3, 8),
17+
)
18+
19+
20+
async def makerandom(delay, threshold=6):
21+
color = COLORS[delay]
22+
print(f"{color}Initiated makerandom({delay}).")
23+
while (number := random.randint(0, 10)) <= threshold:
24+
print(f"{color}makerandom({delay}) == {number} too low; retrying.")
25+
await asyncio.sleep(delay)
26+
print(f"{color}---> Finished: makerandom({delay}) == {number}" + COLORS[0])
27+
return number
28+
29+
30+
if __name__ == "__main__":
31+
random.seed(444)
32+
r1, r2, r3 = asyncio.run(main())
33+
print()
34+
print(f"r1: {r1}, r2: {r2}, r3: {r3}")

0 commit comments

Comments
 (0)