Skip to content

Commit

Permalink
Merge pull request #605 from realpython/python-concurrency
Browse files Browse the repository at this point in the history
Materials for Python Concurrency [UPDATE]
  • Loading branch information
brendaweles authored Nov 4, 2024
2 parents 6726c6a + e453634 commit 214480e
Show file tree
Hide file tree
Showing 17 changed files with 189 additions and 204 deletions.
9 changes: 0 additions & 9 deletions concurrency-overview/README.md

This file was deleted.

21 changes: 0 additions & 21 deletions concurrency-overview/cpu_mp.py

This file was deleted.

20 changes: 0 additions & 20 deletions concurrency-overview/cpu_non_concurrent.py

This file was deleted.

21 changes: 0 additions & 21 deletions concurrency-overview/cpu_threading.py

This file was deleted.

35 changes: 0 additions & 35 deletions concurrency-overview/io_mp.py

This file was deleted.

17 changes: 0 additions & 17 deletions concurrency-overview/race_condition.py

This file was deleted.

35 changes: 0 additions & 35 deletions concurrency-overview/requirements.txt

This file was deleted.

13 changes: 13 additions & 0 deletions python-concurrency/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Speed Up Your Python Program With Concurrency

This folder contains the sample code for the [Speed Up Your Python Program With Concurrency](https://realpython.com/python-concurrency/) tutorial.

To use this code, first create and activate a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/). Then, install the required libraries into it:

```sh
$ python -m venv venv/
$ source venv/bin/activate
(venv) $ python -m pip install -r requirements.txt
```

This will ensure you have the required Python packages.
18 changes: 18 additions & 0 deletions python-concurrency/cpu_asyncio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import asyncio
import time


async def main():
start_time = time.perf_counter()
tasks = [fib(35) for _ in range(20)]
await asyncio.gather(*tasks, return_exceptions=True)
duration = time.perf_counter() - start_time
print(f"Computed in {duration} seconds")


async def fib(n):
return n if n < 2 else await fib(n - 2) + await fib(n - 1)


if __name__ == "__main__":
asyncio.run(main())
17 changes: 17 additions & 0 deletions python-concurrency/cpu_non_concurrent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import time


def main():
start_time = time.perf_counter()
for _ in range(20):
fib(35)
duration = time.perf_counter() - start_time
print(f"Computed in {duration} seconds")


def fib(n):
return n if n < 2 else fib(n - 2) + fib(n - 1)


if __name__ == "__main__":
main()
18 changes: 18 additions & 0 deletions python-concurrency/cpu_processes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import concurrent.futures
import time


def main():
start_time = time.perf_counter()
with concurrent.futures.ProcessPoolExecutor() as executor:
executor.map(fib, [35] * 20)
duration = time.perf_counter() - start_time
print(f"Computed in {duration} seconds")


def fib(n):
return n if n < 2 else fib(n - 2) + fib(n - 1)


if __name__ == "__main__":
main()
18 changes: 18 additions & 0 deletions python-concurrency/cpu_threads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import concurrent.futures
import time


def main():
start_time = time.perf_counter()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
executor.map(fib, [35] * 20)
duration = time.perf_counter() - start_time
print(f"Computed in {duration} seconds")


def fib(n):
return n if n < 2 else fib(n - 2) + fib(n - 1)


if __name__ == "__main__":
main()
32 changes: 16 additions & 16 deletions concurrency-overview/io_asyncio.py → python-concurrency/io_asyncio.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#!/usr/bin/env python3
import asyncio
import time

import aiohttp


async def download_site(session, url):
async with session.get(url) as response:
print("Read {0} from {1}".format(response.content_length, url))
async def main():
sites = [
"https://www.jython.org",
"http://olympus.realpython.org/dice",
] * 80
start_time = time.perf_counter()
await download_all_sites(sites)
duration = time.perf_counter() - start_time
print(f"Downloaded {len(sites)} sites in {duration} seconds")


async def download_all_sites(sites):
async with aiohttp.ClientSession() as session:
tasks = []
for url in sites:
task = asyncio.ensure_future(download_site(session, url))
tasks.append(task)
tasks = [download_site(url, session) for url in sites]
await asyncio.gather(*tasks, return_exceptions=True)


async def download_site(url, session):
async with session.get(url) as response:
print(f"Read {len(await response.read())} bytes from {url}")


if __name__ == "__main__":
sites = [
"https://www.jython.org",
"http://olympus.realpython.org/dice",
] * 80
start_time = time.time()
asyncio.get_event_loop().run_until_complete(download_all_sites(sites))
duration = time.time() - start_time
print(f"Downloaded {len(sites)} sites in {duration} seconds")
asyncio.run(main())
27 changes: 15 additions & 12 deletions concurrency-overview/io_non_concurrent.py → python-concurrency/io_non_concurrent.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#!/usr/bin/env python3
import time

import requests


def download_site(url, session):
with session.get(url) as response:
print(f"Read {len(response.content)} from {url}")
def main():
sites = [
"https://www.jython.org",
"http://olympus.realpython.org/dice",
] * 80
start_time = time.perf_counter()
download_all_sites(sites)
duration = time.perf_counter() - start_time
print(f"Downloaded {len(sites)} sites in {duration} seconds")


def download_all_sites(sites):
Expand All @@ -15,12 +20,10 @@ def download_all_sites(sites):
download_site(url, session)


def download_site(url, session):
with session.get(url) as response:
print(f"Read {len(response.content)} bytes from {url}")


if __name__ == "__main__":
sites = [
"https://www.jython.org",
"http://olympus.realpython.org/dice",
] * 80
start_time = time.time()
download_all_sites(sites)
duration = time.time() - start_time
print(f"Downloaded {len(sites)} in {duration} seconds")
main()
40 changes: 40 additions & 0 deletions python-concurrency/io_processes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import atexit
import multiprocessing
import time
from concurrent.futures import ProcessPoolExecutor

import requests

session: requests.Session


def main():
sites = [
"https://www.jython.org",
"http://olympus.realpython.org/dice",
] * 80
start_time = time.perf_counter()
download_all_sites(sites)
duration = time.perf_counter() - start_time
print(f"Downloaded {len(sites)} sites in {duration} seconds")


def download_all_sites(sites):
with ProcessPoolExecutor(initializer=init_process) as executor:
executor.map(download_site, sites)


def download_site(url):
with session.get(url) as response:
name = multiprocessing.current_process().name
print(f"{name}:Read {len(response.content)} bytes from {url}")


def init_process():
global session
session = requests.Session()
atexit.register(session.close)


if __name__ == "__main__":
main()
Loading

0 comments on commit 214480e

Please sign in to comment.