🎓 A1Learner
🔍

Python Project: Concurrent Fetcher

A concurrent fetcher is a program that fetches several pages at the same time. The pages here are local text in a dict named PAGES.

Pages as local text

Each page is a short string in a dict. The key is the page name.

PAGES = {
    "gamma": "one two three",
    "alpha": "hello world",
    "beta": "python is fun to learn",
}

One slow sync fetch

This fetch assumes time is imported and PAGES exists. It pauses briefly, then builds one report line.

def fetch_page(name):
    time.sleep(0.01)
    text = PAGES[name]
    return f"{name}: {len(text.split())} words"

One slow async fetch

The async twin awaits its pause instead. It builds the same report line.

async def fetch_page_async(name):
    await asyncio.sleep(0.01)
    text = PAGES[name]
    return f"{name}: {len(text.split())} words"

Sort a report

Sorting fixes the line order before you print or compare.

report = ["gamma: 3 words", "alpha: 2 words", "beta: 5 words"]
print(sorted(report))

Example

import asyncio
import time
from concurrent.futures import ThreadPoolExecutor

PAGES = {
    "gamma": "one two three",
    "alpha": "hello world",
    "beta": "python is fun to learn",
}

def fetch_page(name):
    time.sleep(0.01)
    return f"{name}: {len(PAGES[name].split())} words"

async def fetch_page_async(name):
    await asyncio.sleep(0.01)
    return f"{name}: {len(PAGES[name].split())} words"

def fetch_sequential():
    return sorted(fetch_page(name) for name in PAGES)

def fetch_threaded():
    with ThreadPoolExecutor(max_workers=3) as pool:
        return sorted(pool.map(fetch_page, PAGES))

async def fetch_async_all():
    results = await asyncio.gather(
        *(fetch_page_async(name) for name in PAGES)
    )
    return sorted(results)

def show(label, report):
    print(label)
    for line in report:
        print(line)

def main():
    sequential = fetch_sequential()
    threaded = fetch_threaded()
    async_report = asyncio.run(fetch_async_all())
    show("Sequential:", sequential)
    show("Thread pool:", threaded)
    show("Asyncio:", async_report)
    print(f"All three agree: {sequential == threaded == async_report}")

if __name__ == "__main__":
    main()

Key points

  • The pages live in a dict named PAGES.
  • Each fetch adds a tiny delay to act like a slow source.
  • Its fetches run at the same time, not one after another.
  • Use sorted() on each report before you compare reports.
  • Collect results first and print them after each run.
  • Two reports agree when their sorted lines are equal.

In this example, PAGES holds three local pages. fetch_page() pauses for a tiny delay and returns one report line. The sequential run calls it in a generator and sorts the lines. The thread pool run maps it over the page names and sorts the lines. The async run gathers fetch_page_async() calls and sorts its lines. show() prints each sorted report under its label. The last line compares all three lists and prints True.

Note

The three runs print the same report by design.

Compare their structure here, never their speed.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Python Playground

Exercise

Why does the project sort each report before comparing the three runs?