Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 43f1bf2

Browse filesBrowse files
committed
sync from Atlas
1 parent 5d6b156 commit 43f1bf2
Copy full SHA for 43f1bf2

File tree

Expand file treeCollapse file tree

5 files changed

+118
-37
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+118
-37
lines changed

‎19-concurrency/primes/procs.py

Copy file name to clipboardExpand all lines: 19-concurrency/primes/procs.py
+30-30Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,46 +31,46 @@ def worker(jobs: JobQueue, results: ResultQueue) -> None: # <7>
3131
while n := jobs.get(): # <8>
3232
results.put(check(n)) # <9>
3333
results.put(PrimeResult(0, False, 0.0)) # <10>
34-
# end::PRIMES_PROC_TOP[]
3534

36-
# tag::PRIMES_PROC_MIDDLE[]
37-
def start_jobs(workers: int, jobs: JobQueue, results: ResultQueue) -> None:
35+
def start_jobs(
36+
procs: int, jobs: JobQueue, results: ResultQueue # <11>
37+
) -> None:
3838
for n in NUMBERS:
39-
jobs.put(n) # <1>
40-
for _ in range(workers):
41-
proc = Process(target=worker, args=(jobs, results)) # <2>
42-
proc.start() # <3>
43-
jobs.put(0) # <4>
44-
45-
def report(workers: int, results: ResultQueue) -> int:
46-
checked = 0
47-
workers_done = 0
48-
while workers_done < workers:
49-
n, prime, elapsed = results.get()
50-
if n == 0:
51-
workers_done += 1
52-
else:
53-
checked += 1
54-
label = 'P' if prime else ' '
55-
print(f'{n:16} {label} {elapsed:9.6f}s')
56-
return checked
57-
# end::PRIMES_PROC_MIDDLE[]
39+
jobs.put(n) # <12>
40+
for _ in range(procs):
41+
proc = Process(target=worker, args=(jobs, results)) # <13>
42+
proc.start() # <14>
43+
jobs.put(0) # <15>
44+
# end::PRIMES_PROC_TOP[]
5845

5946
# tag::PRIMES_PROC_MAIN[]
6047
def main() -> None:
61-
if len(sys.argv) < 2:
62-
workers = cpu_count()
48+
if len(sys.argv) < 2: # <1>
49+
procs = cpu_count()
6350
else:
64-
workers = int(sys.argv[1])
51+
procs = int(sys.argv[1])
6552

66-
print(f'Checking {len(NUMBERS)} numbers with {workers} processes:')
53+
print(f'Checking {len(NUMBERS)} numbers with {procs} processes:')
6754
t0 = perf_counter()
68-
jobs: JobQueue = SimpleQueue()
55+
jobs: JobQueue = SimpleQueue() # <2>
6956
results: ResultQueue = SimpleQueue()
70-
start_jobs(workers, jobs, results)
71-
checked = report(workers, results)
57+
start_jobs(procs, jobs, results) # <3>
58+
checked = report(procs, results) # <4>
7259
elapsed = perf_counter() - t0
73-
print(f'{checked} checks in {elapsed:.2f}s')
60+
print(f'{checked} checks in {elapsed:.2f}s') # <5>
61+
62+
def report(procs: int, results: ResultQueue) -> int: # <6>
63+
checked = 0
64+
procs_done = 0
65+
while procs_done < procs: # <7>
66+
n, prime, elapsed = results.get() # <8>
67+
if n == 0: # <9>
68+
procs_done += 1
69+
else:
70+
checked += 1 # <10>
71+
label = 'P' if prime else ' '
72+
print(f'{n:16} {label} {elapsed:9.6f}s')
73+
return checked
7474

7575
if __name__ == '__main__':
7676
main()
+80Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
procs.py: shows that multiprocessing on a multicore machine
5+
can be faster than sequential code for CPU-intensive work.
6+
"""
7+
8+
# tag::PRIMES_PROC_TOP[]
9+
import sys
10+
from time import perf_counter
11+
from typing import NamedTuple
12+
from multiprocessing import Process, SimpleQueue, cpu_count # <1>
13+
from multiprocessing import queues # <2>
14+
15+
from primes import is_prime, NUMBERS
16+
17+
class PrimeResult(NamedTuple): # <3>
18+
n: int
19+
prime: bool
20+
elapsed: float
21+
22+
JobQueue = queues.SimpleQueue[int] # <4>
23+
ResultQueue = queues.SimpleQueue[PrimeResult] # <5>
24+
25+
def check(n: int) -> PrimeResult: # <6>
26+
t0 = perf_counter()
27+
res = is_prime(n)
28+
return PrimeResult(n, res, perf_counter() - t0)
29+
30+
def worker(jobs: JobQueue, results: ResultQueue) -> None: # <7>
31+
while n := jobs.get(): # <8>
32+
results.put(check(n)) # <9>
33+
results.put(PrimeResult(0, False, 0.0))
34+
# end::PRIMES_PROC_TOP[]
35+
36+
def start_jobs(workers: int) -> ResultQueue:
37+
jobs: JobQueue = SimpleQueue() # <2>
38+
results: ResultQueue = SimpleQueue()
39+
40+
for n in NUMBERS: # <3>
41+
jobs.put(n)
42+
43+
for _ in range(workers):
44+
proc = Process(target=worker, args=(jobs, results)) # <4>
45+
proc.start() # <5>
46+
jobs.put(0) # <6>
47+
48+
return results
49+
50+
def report(workers: int, results: ResultQueue) -> int:
51+
workers_done = 0
52+
checked = 0
53+
while workers_done < workers:
54+
n, prime, elapsed = results.get() # <7>
55+
if n == 0:
56+
workers_done += 1
57+
else:
58+
checked += 1
59+
label = 'P' if prime else ' '
60+
print(f'{n:16} {label} {elapsed:9.6f}s') # <8>
61+
return checked
62+
63+
64+
# tag::PRIMES_PROC_MAIN[]
65+
def main() -> None:
66+
if len(sys.argv) < 2: # <1>
67+
workers = cpu_count()
68+
else:
69+
workers = int(sys.argv[1])
70+
71+
print(f'Checking {len(NUMBERS)} numbers with {workers} processes:')
72+
t0 = perf_counter()
73+
results = start_jobs(workers)
74+
checked = report(workers, results)
75+
elapsed = perf_counter() - t0
76+
print(f'{checked} checks in {elapsed:.2f}s')
77+
78+
if __name__ == '__main__':
79+
main()
80+
# end::PRIMES_PROC_MAIN[]

‎20-executors/getflags/.gitignore

Copy file name to clipboard
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
flags/
1+
flags/
2+
downloaded/

‎20-executors/getflags/flags2_threadpool.py

Copy file name to clipboardExpand all lines: 20-executors/getflags/flags2_threadpool.py
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
# tag::FLAGS2_THREADPOOL[]
2222
from collections import Counter
23-
from concurrent import futures
23+
from concurrent.futures import ThreadPoolExecutor, as_completed
2424

2525
import httpx
2626
import tqdm # type: ignore
@@ -37,13 +37,13 @@ def download_many(cc_list: list[str],
3737
verbose: bool,
3838
concur_req: int) -> Counter[DownloadStatus]:
3939
counter: Counter[DownloadStatus] = Counter()
40-
with futures.ThreadPoolExecutor(max_workers=concur_req) as executor: # <4>
40+
with ThreadPoolExecutor(max_workers=concur_req) as executor: # <4>
4141
to_do_map = {} # <5>
4242
for cc in sorted(cc_list): # <6>
4343
future = executor.submit(download_one, cc,
4444
base_url, verbose) # <7>
4545
to_do_map[future] = cc # <8>
46-
done_iter = futures.as_completed(to_do_map) # <9>
46+
done_iter = as_completed(to_do_map) # <9>
4747
if not verbose:
4848
done_iter = tqdm.tqdm(done_iter, total=len(cc_list)) # <10>
4949
for future in done_iter: # <11>
@@ -52,7 +52,7 @@ def download_many(cc_list: list[str],
5252
except httpx.HTTPStatusError as exc: # <13>
5353
error_msg = 'HTTP error {resp.status_code} - {resp.reason_phrase}'
5454
error_msg = error_msg.format(resp=exc.response)
55-
except httpx.RequestError as exc: # <15>
55+
except httpx.RequestError as exc:
5656
error_msg = f'{exc} {type(exc)}'.strip()
5757
except KeyboardInterrupt:
5858
break
@@ -63,7 +63,7 @@ def download_many(cc_list: list[str],
6363
status = DownloadStatus.ERROR
6464
counter[status] += 1
6565
if verbose and error_msg:
66-
cc = to_do_map[future] # <16>
66+
cc = to_do_map[future] # <14>
6767
print(f'{cc} error: {error_msg}')
6868

6969
return counter

‎README.md

Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Part / Chapter #|Title|Directory|1<sup>st</sup> ed. Chapter&nbsp;#
4444
17|Iterators, Generators, and Classic Coroutines|[17-it-generator](17-it-generator)|14
4545
18|Context Managers and else Blocks|[18-with-match](18-with-match)|15
4646
19|Concurrency Models in Python|[19-concurrency](19-concurrency)|🆕
47-
20|Concurrency with Futures|[20-futures](20-futures)|17
47+
20|Concurrent Executors|[20-executors](20-executors)|17
4848
21|Asynchronous Programming|[21-async](21-async)|18
4949
**VI – Metaprogramming**|
5050
22|Dynamic Attributes and Properties|[22-dyn-attr-prop](22-dyn-attr-prop)|19

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.