From 3db299aef5cddd28873aa6eebfbe465196151376 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Wed, 29 Jul 2026 10:57:15 +0000 Subject: [PATCH 1/2] Update async features examples for Python 3.14 Refresh the code for the "Getting Started With Async Features in Python" tutorial update. - Replace the `done`-flag loops with `while tasks:`, and iterate over a copy so removing an exhausted generator can't skip a task - Switch `asyncio.gather()` to `async with asyncio.TaskGroup()` in examples 4 and 6 (Python 3.11+) - Guard each HTTP request in example 6 with `asyncio.timeout(10)` - Rename the `queue` parameter to `work_queue` so it stops shadowing the `queue` module - Drop the stray `from builtins import range` in example 2 - Move the URL lists to https and replace the dead entries (twitter.com now redirects to x.com, yahoo.com returns 404) - Refresh requirements.txt to current releases and drop the transitive pins All six examples verified on Python 3.14.6. Co-Authored-By: Claude Opus 5 (1M context) --- .../example_2.py | 14 ++++------- .../example_3.py | 13 ++++------ .../example_4.py | 7 +++--- .../example_5.py | 20 ++++++--------- .../example_6.py | 25 +++++++++---------- .../requirements.txt | 14 +++-------- 6 files changed, 36 insertions(+), 57 deletions(-) diff --git a/understanding-asynchronous-programming/example_2.py b/understanding-asynchronous-programming/example_2.py index 53c6b8ca27..520522dc09 100644 --- a/understanding-asynchronous-programming/example_2.py +++ b/understanding-asynchronous-programming/example_2.py @@ -1,10 +1,9 @@ import queue -from builtins import range -def task(name, queue): - while not queue.empty(): - count = queue.get() +def task(name, work_queue): + while not work_queue.empty(): + count = work_queue.get() total = 0 print(f"Task {name} running") for x in range(count): @@ -28,15 +27,12 @@ def main(): tasks = [task("One", work_queue), task("Two", work_queue)] # Run the tasks - done = False - while not done: - for t in tasks: + while tasks: + for t in tasks.copy(): try: next(t) except StopIteration: tasks.remove(t) - if len(tasks) == 0: - done = True if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_3.py b/understanding-asynchronous-programming/example_3.py index 6a5aa34b4c..d74af9ab46 100644 --- a/understanding-asynchronous-programming/example_3.py +++ b/understanding-asynchronous-programming/example_3.py @@ -4,10 +4,10 @@ from codetiming import Timer -def task(name, queue): +def task(name, work_queue): timer = Timer(text=f"Task {name} elapsed time: {{:.1f}}") - while not queue.empty(): - delay = queue.get() + while not work_queue.empty(): + delay = work_queue.get() print(f"Task {name} running") timer.start() time.sleep(delay) @@ -29,16 +29,13 @@ def main(): tasks = [task("One", work_queue), task("Two", work_queue)] # Run the tasks - done = False with Timer(text="\nTotal elapsed time: {:.1f}"): - while not done: - for t in tasks: + while tasks: + for t in tasks.copy(): try: next(t) except StopIteration: tasks.remove(t) - if len(tasks) == 0: - done = True if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_4.py b/understanding-asynchronous-programming/example_4.py index d95bb62b43..941da9d3f7 100644 --- a/understanding-asynchronous-programming/example_4.py +++ b/understanding-asynchronous-programming/example_4.py @@ -26,10 +26,9 @@ async def main(): # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): - await asyncio.gather( - asyncio.create_task(task("One", work_queue)), - asyncio.create_task(task("Two", work_queue)), - ) + async with asyncio.TaskGroup() as group: + group.create_task(task("One", work_queue)) + group.create_task(task("Two", work_queue)) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_5.py b/understanding-asynchronous-programming/example_5.py index afea769218..fbf8b27910 100644 --- a/understanding-asynchronous-programming/example_5.py +++ b/understanding-asynchronous-programming/example_5.py @@ -25,29 +25,25 @@ def main(): # Put some work in the queue for url in [ - "http://google.com", - "http://yahoo.com", - "http://linkedin.com", - "http://apple.com", - "http://microsoft.com", - "http://facebook.com", - "http://twitter.com", + "https://www.google.com", + "https://www.linkedin.com", + "https://www.apple.com", + "https://www.microsoft.com", + "https://www.facebook.com", + "https://x.com", ]: work_queue.put(url) tasks = [task("One", work_queue), task("Two", work_queue)] # Run the tasks - done = False with Timer(text="\nTotal elapsed time: {:.1f}"): - while not done: - for t in tasks: + while tasks: + for t in tasks.copy(): try: next(t) except StopIteration: tasks.remove(t) - if len(tasks) == 0: - done = True if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_6.py b/understanding-asynchronous-programming/example_6.py index 1f4e3d2810..191eefe61a 100644 --- a/understanding-asynchronous-programming/example_6.py +++ b/understanding-asynchronous-programming/example_6.py @@ -11,8 +11,9 @@ async def task(name, work_queue): url = await work_queue.get() print(f"Task {name} getting URL: {url}") timer.start() - async with session.get(url) as response: - await response.text() + async with asyncio.timeout(10): + async with session.get(url) as response: + await response.text() timer.stop() @@ -25,22 +26,20 @@ async def main(): # Put some work in the queue for url in [ - "http://google.com", - "http://yahoo.com", - "http://linkedin.com", - "http://apple.com", - "http://microsoft.com", - "http://facebook.com", - "http://twitter.com", + "https://www.google.com", + "https://www.linkedin.com", + "https://www.apple.com", + "https://www.microsoft.com", + "https://www.facebook.com", + "https://x.com", ]: await work_queue.put(url) # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): - await asyncio.gather( - asyncio.create_task(task("One", work_queue)), - asyncio.create_task(task("Two", work_queue)), - ) + async with asyncio.TaskGroup() as group: + group.create_task(task("One", work_queue)) + group.create_task(task("Two", work_queue)) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/requirements.txt b/understanding-asynchronous-programming/requirements.txt index e5f9331f7e..e55d45505d 100644 --- a/understanding-asynchronous-programming/requirements.txt +++ b/understanding-asynchronous-programming/requirements.txt @@ -1,11 +1,3 @@ -aiohttp==3.5.4 -async-timeout==3.0.1 -attrs==19.1.0 -certifi==2019.3.9 -chardet==3.0.4 -codetiming==0.1.2 -idna==2.8 -multidict==4.5.2 -requests==2.21.0 -urllib3==1.24.2 -yarl==1.3.0 +aiohttp==3.14.3 +codetiming==1.4.0 +requests==2.34.2 From c733f89895016f09dabdfd6fb66671431b03e24a Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Wed, 29 Jul 2026 16:03:54 +0000 Subject: [PATCH 2/2] Polish async examples for readability Follow-up to the Python 3.14 refresh, applying review feedback on the sample code for "Getting Started With Async Features in Python". - Replace the `else` branch in example 1 with an early `return`, so the main loop body isn't indented behind a conditional - Name the loop variables in example 1's runner (`task_func`, `task_name`, `tasks_queue`) instead of `t`, `n`, `q` - Rename `t` to `current_task` in the generator-driving loops of examples 2, 3, and 5 - Use `_` for the unused counter variable in examples 1 and 2 - Extract the URL lists in examples 5 and 6 into a `urls` variable rather than inlining them in the `for` statement header - Drop the boilerplate docstrings and step comments, which restated what the code already says All six examples verified on Python 3.14.6 against the tutorial output. Co-Authored-By: Claude Opus 5 (1M context) --- .../example_1.py | 29 +++++++------------ .../example_2.py | 16 +++------- .../example_3.py | 13 ++------- .../example_4.py | 7 ----- .../example_5.py | 21 +++++--------- .../example_6.py | 15 ++++------ 6 files changed, 31 insertions(+), 70 deletions(-) diff --git a/understanding-asynchronous-programming/example_1.py b/understanding-asynchronous-programming/example_1.py index 0b8529e5ce..2592b0a18f 100644 --- a/understanding-asynchronous-programming/example_1.py +++ b/understanding-asynchronous-programming/example_1.py @@ -4,33 +4,26 @@ def task(name, work_queue): if work_queue.empty(): print(f"Task {name} nothing to do") - else: - while not work_queue.empty(): - count = work_queue.get() - total = 0 - print(f"Task {name} running") - for x in range(count): - total += 1 - print(f"Task {name} total: {total}") + return + + while not work_queue.empty(): + count = work_queue.get() + total = 0 + print(f"Task {name} running") + for _ in range(count): + total += 1 + print(f"Task {name} total: {total}") def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work work_queue = queue.Queue() - - # Put some work in the queue for work in [15, 10, 5, 2]: work_queue.put(work) - # Create some synchronous tasks tasks = [(task, "One", work_queue), (task, "Two", work_queue)] - # Run the tasks - for t, n, q in tasks: - t(n, q) + for task_func, task_name, tasks_queue in tasks: + task_func(task_name, tasks_queue) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_2.py b/understanding-asynchronous-programming/example_2.py index 520522dc09..1e543ad390 100644 --- a/understanding-asynchronous-programming/example_2.py +++ b/understanding-asynchronous-programming/example_2.py @@ -6,33 +6,25 @@ def task(name, work_queue): count = work_queue.get() total = 0 print(f"Task {name} running") - for x in range(count): + for _ in range(count): total += 1 yield print(f"Task {name} total: {total}") def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work work_queue = queue.Queue() - - # Put some work in the queue for work in [15, 10, 5, 2]: work_queue.put(work) - # Create some tasks tasks = [task("One", work_queue), task("Two", work_queue)] - # Run the tasks while tasks: - for t in tasks.copy(): + for current_task in tasks.copy(): try: - next(t) + next(current_task) except StopIteration: - tasks.remove(t) + tasks.remove(current_task) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_3.py b/understanding-asynchronous-programming/example_3.py index d74af9ab46..381a49bf6d 100644 --- a/understanding-asynchronous-programming/example_3.py +++ b/understanding-asynchronous-programming/example_3.py @@ -16,26 +16,19 @@ def task(name, work_queue): def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work work_queue = queue.Queue() - - # Put some work in the queue for work in [15, 10, 5, 2]: work_queue.put(work) tasks = [task("One", work_queue), task("Two", work_queue)] - # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): while tasks: - for t in tasks.copy(): + for current_task in tasks.copy(): try: - next(t) + next(current_task) except StopIteration: - tasks.remove(t) + tasks.remove(current_task) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_4.py b/understanding-asynchronous-programming/example_4.py index 941da9d3f7..b6703b616f 100644 --- a/understanding-asynchronous-programming/example_4.py +++ b/understanding-asynchronous-programming/example_4.py @@ -14,17 +14,10 @@ async def task(name, work_queue): async def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work work_queue = asyncio.Queue() - - # Put some work in the queue for work in [15, 10, 5, 2]: await work_queue.put(work) - # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): async with asyncio.TaskGroup() as group: group.create_task(task("One", work_queue)) diff --git a/understanding-asynchronous-programming/example_5.py b/understanding-asynchronous-programming/example_5.py index fbf8b27910..6e3977fc94 100644 --- a/understanding-asynchronous-programming/example_5.py +++ b/understanding-asynchronous-programming/example_5.py @@ -17,33 +17,28 @@ def task(name, work_queue): def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work - work_queue = queue.Queue() - - # Put some work in the queue - for url in [ + urls = [ "https://www.google.com", "https://www.linkedin.com", "https://www.apple.com", "https://www.microsoft.com", "https://www.facebook.com", "https://x.com", - ]: + ] + + work_queue = queue.Queue() + for url in urls: work_queue.put(url) tasks = [task("One", work_queue), task("Two", work_queue)] - # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): while tasks: - for t in tasks.copy(): + for current_task in tasks.copy(): try: - next(t) + next(current_task) except StopIteration: - tasks.remove(t) + tasks.remove(current_task) if __name__ == "__main__": diff --git a/understanding-asynchronous-programming/example_6.py b/understanding-asynchronous-programming/example_6.py index 191eefe61a..342bc0379b 100644 --- a/understanding-asynchronous-programming/example_6.py +++ b/understanding-asynchronous-programming/example_6.py @@ -18,24 +18,19 @@ async def task(name, work_queue): async def main(): - """ - This is the main entry point for the program - """ - # Create the queue of work - work_queue = asyncio.Queue() - - # Put some work in the queue - for url in [ + urls = [ "https://www.google.com", "https://www.linkedin.com", "https://www.apple.com", "https://www.microsoft.com", "https://www.facebook.com", "https://x.com", - ]: + ] + + work_queue = asyncio.Queue() + for url in urls: await work_queue.put(url) - # Run the tasks with Timer(text="\nTotal elapsed time: {:.1f}"): async with asyncio.TaskGroup() as group: group.create_task(task("One", work_queue))