or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-greenlets.mdindex.mdmonkey-patching.mdnetworking.mdpooling.mdqueues.mdservers.mdsynchronization.mdtimeouts.md

monkey-patching.mddocs/

0

# Monkey Patching

1

2

Transparent replacement of standard library modules with gevent-aware equivalents, enabling existing code to work cooperatively without modification. Monkey patching is gevent's mechanism for making synchronous code asynchronous.

3

4

## Capabilities

5

6

### Core Patching Functions

7

8

Main functions for applying monkey patches to standard library modules.

9

10

```python { .api }

11

def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, subprocess=True, sys=False, aggressive=True, Event=True, builtins=True, signal=True, queue=True, contextvars=True, **kwargs):

12

"""

13

Patch all supported modules with gevent equivalents.

14

15

Parameters:

16

- socket: bool, patch socket module

17

- dns: bool, patch DNS functions

18

- time: bool, patch time.sleep

19

- select: bool, patch select module

20

- thread: bool, patch thread module

21

- os: bool, patch os module

22

- ssl: bool, patch ssl module

23

- subprocess: bool, patch subprocess module

24

- sys: bool, patch sys module

25

- aggressive: bool, more comprehensive patching

26

- Event: bool, patch threading.Event

27

- builtins: bool, patch builtin functions

28

- signal: bool, patch signal module

29

- queue: bool, patch queue module

30

- contextvars: bool, patch contextvars module

31

- **kwargs: additional patching options

32

33

Returns:

34

None

35

"""

36

37

def patch_socket():

38

"""

39

Patch socket module with gevent socket.

40

41

Returns:

42

None

43

"""

44

45

def patch_ssl():

46

"""

47

Patch ssl module with gevent ssl.

48

49

Returns:

50

None

51

"""

52

53

def patch_thread():

54

"""

55

Patch thread module with gevent equivalents.

56

57

Returns:

58

None

59

"""

60

61

def patch_threading():

62

"""

63

Patch threading module with gevent equivalents.

64

65

Returns:

66

None

67

"""

68

69

def patch_select():

70

"""

71

Patch select module with gevent select.

72

73

Returns:

74

None

75

"""

76

77

def patch_subprocess():

78

"""

79

Patch subprocess module with gevent subprocess.

80

81

Returns:

82

None

83

"""

84

85

def patch_os():

86

"""

87

Patch os module functions with cooperative versions.

88

89

Returns:

90

None

91

"""

92

93

def patch_time():

94

"""

95

Patch time.sleep with gevent.sleep.

96

97

Returns:

98

None

99

"""

100

101

def patch_sys():

102

"""

103

Patch sys module functions.

104

105

Returns:

106

None

107

"""

108

109

def patch_builtins():

110

"""

111

Patch builtin functions with cooperative versions.

112

113

Returns:

114

None

115

"""

116

117

def patch_signal():

118

"""

119

Patch signal module with gevent signal handling.

120

121

Returns:

122

None

123

"""

124

125

def patch_queue():

126

"""

127

Patch queue module with gevent queue.

128

129

Returns:

130

None

131

"""

132

133

def patch_dns():

134

"""

135

Patch DNS resolution functions.

136

137

Returns:

138

None

139

"""

140

```

141

142

### Utility Functions

143

144

Functions for inspecting and managing monkey patches.

145

146

```python { .api }

147

def get_original(module_name, item_name):

148

"""

149

Get original (unpatched) function or class.

150

151

Parameters:

152

- module_name: str, name of module

153

- item_name: str, name of item in module

154

155

Returns:

156

Original unpatched object

157

"""

158

159

def is_module_patched(module) -> bool:

160

"""

161

Check if module has been monkey patched.

162

163

Parameters:

164

- module: module object or string name

165

166

Returns:

167

bool, True if module is patched

168

"""

169

170

def is_object_patched(obj) -> bool:

171

"""

172

Check if specific object has been patched.

173

174

Parameters:

175

- obj: object to check

176

177

Returns:

178

bool, True if object is patched

179

"""

180

```

181

182

### Exceptions

183

184

```python { .api }

185

class MonkeyPatchWarning(Warning):

186

"""Warning raised for monkey patching issues."""

187

```

188

189

## Usage Examples

190

191

### Basic Monkey Patching

192

193

```python

194

# This should be done at the very start of your program

195

from gevent import monkey

196

monkey.patch_all()

197

198

# Now all standard library I/O is cooperative

199

import socket

200

import time

201

import threading

202

203

def blocking_function():

204

# This appears to block but actually yields to other greenlets

205

time.sleep(2)

206

207

# Socket operations are now cooperative

208

s = socket.socket()

209

s.connect(('google.com', 80))

210

s.send(b'GET / HTTP/1.1\r\nHost: google.com\r\n\r\n')

211

response = s.recv(1024)

212

s.close()

213

214

return response[:100]

215

216

# Can be used with gevent as normal

217

import gevent

218

greenlets = [gevent.spawn(blocking_function) for _ in range(10)]

219

results = [g.get() for g in greenlets]

220

print(f"Got {len(results)} responses")

221

```

222

223

### Selective Patching

224

225

```python

226

from gevent import monkey

227

228

# Only patch specific modules

229

monkey.patch_socket()

230

monkey.patch_ssl()

231

monkey.patch_time()

232

233

import socket

234

import ssl

235

import time

236

237

def selective_example():

238

# Socket and SSL are cooperative

239

context = ssl.create_default_context()

240

with socket.create_connection(('httpbin.org', 443)) as sock:

241

with context.wrap_socket(sock, server_hostname='httpbin.org') as ssock:

242

ssock.send(b'GET /get HTTP/1.1\r\nHost: httpbin.org\r\n\r\n')

243

244

# time.sleep is cooperative

245

time.sleep(0.1)

246

247

response = ssock.recv(1024)

248

return response

249

250

result = selective_example()

251

print("Response received")

252

```

253

254

### Checking Patch Status

255

256

```python

257

from gevent import monkey

258

import socket

259

import threading

260

261

def check_patches():

262

print("Before patching:")

263

print(f"Socket module patched: {monkey.is_module_patched('socket')}")

264

print(f"Threading module patched: {monkey.is_module_patched('threading')}")

265

print(f"Socket.socket patched: {monkey.is_object_patched(socket.socket)}")

266

267

# Apply patches

268

monkey.patch_all()

269

270

print("\nAfter patching:")

271

print(f"Socket module patched: {monkey.is_module_patched('socket')}")

272

print(f"Threading module patched: {monkey.is_module_patched('threading')}")

273

print(f"Socket.socket patched: {monkey.is_object_patched(socket.socket)}")

274

275

check_patches()

276

```

277

278

### Getting Original Functions

279

280

```python

281

from gevent import monkey

282

283

# Patch everything

284

monkey.patch_all()

285

286

import time

287

import socket

288

289

# Get original functions

290

original_sleep = monkey.get_original('time', 'sleep')

291

original_socket = monkey.get_original('socket', 'socket')

292

293

def mixed_example():

294

print("Using gevent sleep (cooperative)")

295

time.sleep(1) # This is now gevent.sleep

296

297

print("Using original sleep (blocking)")

298

original_sleep(1) # This is the original time.sleep

299

300

print("Using gevent socket (cooperative)")

301

gevent_sock = socket.socket() # This is gevent socket

302

303

print("Using original socket (blocking)")

304

original_sock = original_socket() # This is original socket

305

306

mixed_example()

307

```

308

309

### Patching for Existing Code

310

311

```python

312

# At the top of your main script

313

from gevent import monkey

314

monkey.patch_all()

315

316

# Now existing libraries work cooperatively

317

import requests # Uses patched socket/ssl

318

import urllib3 # Uses patched socket/ssl

319

import time # sleep is cooperative

320

321

def fetch_urls(urls):

322

"""This function can now handle many concurrent requests."""

323

import gevent

324

325

def fetch_one(url):

326

try:

327

# requests will use gevent sockets automatically

328

response = requests.get(url, timeout=5)

329

return f"{url}: {response.status_code}"

330

except Exception as e:

331

return f"{url}: Error - {e}"

332

333

# Spawn greenlets for concurrent fetching

334

greenlets = [gevent.spawn(fetch_one, url) for url in urls]

335

336

# Wait for all to complete

337

gevent.joinall(greenlets)

338

339

# Collect results

340

return [g.value for g in greenlets]

341

342

# Test with multiple URLs

343

urls = [

344

'http://httpbin.org/delay/1',

345

'http://httpbin.org/delay/2',

346

'http://httpbin.org/delay/1',

347

'http://httpbin.org/status/200',

348

'http://httpbin.org/status/404'

349

]

350

351

results = fetch_urls(urls)

352

for result in results:

353

print(result)

354

```

355

356

### Database Connection Pooling

357

358

```python

359

from gevent import monkey

360

monkey.patch_all()

361

362

import gevent

363

import time

364

import sqlite3

365

366

# Simulate a database connection pool

367

class DatabasePool:

368

def __init__(self, size=5):

369

self.connections = []

370

for i in range(size):

371

# Each connection would be a real DB connection

372

self.connections.append(f"connection_{i}")

373

self.available = list(self.connections)

374

self.in_use = []

375

376

def get_connection(self):

377

while not self.available:

378

time.sleep(0.1) # Cooperative wait

379

conn = self.available.pop()

380

self.in_use.append(conn)

381

return conn

382

383

def return_connection(self, conn):

384

if conn in self.in_use:

385

self.in_use.remove(conn)

386

self.available.append(conn)

387

388

def database_worker(worker_id, pool):

389

conn = pool.get_connection()

390

print(f"Worker {worker_id} got {conn}")

391

392

# Simulate database work

393

time.sleep(2) # This is now cooperative

394

395

print(f"Worker {worker_id} finished with {conn}")

396

pool.return_connection(conn)

397

398

return f"Worker {worker_id} completed"

399

400

# Create pool and workers

401

pool = DatabasePool(3) # Only 3 connections available

402

workers = [gevent.spawn(database_worker, i, pool) for i in range(10)]

403

404

# Wait for all workers

405

results = [w.get() for w in workers]

406

print(f"All workers completed: {len(results)}")

407

```

408

409

### Testing Patch Compatibility

410

411

```python

412

from gevent import monkey

413

import warnings

414

415

def test_patching():

416

# Capture warnings

417

with warnings.catch_warnings(record=True) as w:

418

warnings.simplefilter("always")

419

420

# Apply patches

421

monkey.patch_all()

422

423

# Check for warnings

424

if w:

425

print("Monkey patching warnings:")

426

for warning in w:

427

print(f" {warning.message}")

428

else:

429

print("No monkey patching warnings")

430

431

# Test basic functionality

432

import socket

433

import time

434

import threading

435

436

print("Testing patched modules:")

437

438

# Test socket

439

try:

440

s = socket.socket()

441

s.settimeout(1)

442

s.connect(('8.8.8.8', 53))

443

s.close()

444

print(" Socket: OK")

445

except Exception as e:

446

print(f" Socket: Error - {e}")

447

448

# Test time

449

start = time.time()

450

time.sleep(0.01)

451

elapsed = time.time() - start

452

print(f" Time.sleep: {elapsed:.3f}s (expected ~0.01s)")

453

454

# Test threading

455

try:

456

event = threading.Event()

457

event.set()

458

print(f" Threading.Event: {'OK' if event.is_set() else 'Error'}")

459

except Exception as e:

460

print(f" Threading: Error - {e}")

461

462

test_patching()

463

```