-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexamples.py
More file actions
118 lines (95 loc) · 5.31 KB
/
Copy pathexamples.py
File metadata and controls
118 lines (95 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""
Chapter 19: Concurrency Models in Python
========================================
Original implementations exploring the three major concurrency
paradigms in Python: threading, multiprocessing, and asyncio.
Key concepts covered:
- Preemptive multitasking (Threads & Processes)
- Cooperative multitasking (Asyncio)
- Memory separation (Processes) vs Shared memory (Threads)
"""
import sys
import time
import itertools
import threading
import multiprocessing
import asyncio
sys.stdout.reconfigure(encoding="utf-8")
def section(title: str) -> None:
print(f"\n{'=' * 60}\n=== {title}\n{'=' * 60}")
# ─────────────────────────────────────────────────────────────────────────────
# 1. Threading Spinner (Preemptive, Shared Memory, GIL Restricted)
# ─────────────────────────────────────────────────────────────────────────────
def spin_thread(msg: str, done: threading.Event) -> None:
"""A background thread function."""
for char in itertools.cycle(r'\|/-'):
status = f'\r{char} {msg}'
print(status, end='', flush=True)
if done.wait(0.1): # Wait blocks for 0.1s, returning True if flag is set
break
print('\r' + ' ' * len(status) + '\r', end='')
def demo_threading() -> None:
section("Part 1: Threading (Preemptive)")
done = threading.Event()
# Threads share the exact same memory space and are managed by the OS.
spinner = threading.Thread(target=spin_thread, args=('Thinking (Thread)...', done))
spinner.start()
time.sleep(2) # Simulating I/O bound work on main thread. GIL is released here!
done.set() # Set flag to stop the thread
spinner.join()
print("Done threading!")
# ─────────────────────────────────────────────────────────────────────────────
# 2. Multiprocessing Spinner (Preemptive, Isolated Memory, GIL Bypassed)
# ─────────────────────────────────────────────────────────────────────────────
def spin_process(msg: str, done: multiprocessing.Event) -> None:
"""A background process function."""
for char in itertools.cycle(r'\|/-'):
status = f'\r{char} {msg}'
print(status, end='', flush=True)
if done.wait(0.1):
break
print('\r' + ' ' * len(status) + '\r', end='')
def demo_multiprocessing() -> None:
section("Part 2: Multiprocessing (Parallelism)")
# Must use multiprocessing.Event, not threading.Event!
done = multiprocessing.Event()
# Processes launch an entirely new Python interpreter. Heavy overhead!
spinner = multiprocessing.Process(target=spin_process, args=('Thinking (Process)...', done))
spinner.start()
time.sleep(2) # Simulating CPU/IO bound work
done.set()
spinner.join()
print("Done multiprocessing!")
# ─────────────────────────────────────────────────────────────────────────────
# 3. Asyncio Spinner (Cooperative, Single Thread, Event Loop)
# ─────────────────────────────────────────────────────────────────────────────
async def spin_async(msg: str) -> None:
"""A coroutine managed by the event loop."""
for char in itertools.cycle(r'\|/-'):
status = f'\r{char} {msg}'
print(status, end='', flush=True)
try:
# Yield control back to the event loop cooperatively
await asyncio.sleep(0.1)
except asyncio.CancelledError:
break
print('\r' + ' ' * len(status) + '\r', end='')
async def run_async_demo() -> None:
# Schedule the coroutine to run on the event loop
spinner = asyncio.create_task(spin_async('Thinking (Asyncio)...'))
# Simulate work. `await` yields control back to the loop, letting the spinner run.
await asyncio.sleep(2)
# Cancel the task explicitly
spinner.cancel()
print("Done asyncio!")
def demo_asyncio() -> None:
section("Part 3: Asyncio (Cooperative)")
asyncio.run(run_async_demo())
# ─────────────────────────────────────────────────────────────────────────────
# MAIN
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
# In Windows, multiprocessing MUST be protected by the __main__ block
demo_threading()
demo_multiprocessing()
demo_asyncio()