0
# Green Standard Library
1
2
Cooperative versions of Python standard library modules that work seamlessly with eventlet's green threading model. The `eventlet.green` package provides drop-in replacements for standard library modules.
3
4
## Capabilities
5
6
### Core Green Modules
7
8
Essential modules that provide the foundation for cooperative I/O operations.
9
10
```python { .api }
11
# Socket operations
12
import eventlet.green.socket as socket
13
# SSL/TLS support
14
import eventlet.green.ssl as ssl
15
# I/O multiplexing
16
import eventlet.green.select as select
17
# Threading primitives
18
import eventlet.green.threading as threading
19
# Time operations
20
import eventlet.green.time as time
21
# OS operations
22
import eventlet.green.os as os
23
# Process management
24
import eventlet.green.subprocess as subprocess
25
```
26
27
### HTTP and Web Modules
28
29
Green versions of HTTP client and server modules for web applications.
30
31
```python { .api }
32
# HTTP client operations
33
import eventlet.green.http.client as http_client
34
# HTTP server operations
35
import eventlet.green.http.server as http_server
36
# HTTP cookie handling
37
import eventlet.green.http.cookies as http_cookies
38
# HTTP cookie jar
39
import eventlet.green.http.cookiejar as http_cookiejar
40
```
41
42
### URL and Request Handling
43
44
Green versions of URL parsing and request handling modules.
45
46
```python { .api }
47
# URL parsing utilities
48
import eventlet.green.urllib.parse as urllib_parse
49
# URL request handling
50
import eventlet.green.urllib.request as urllib_request
51
# URL error handling
52
import eventlet.green.urllib.error as urllib_error
53
# Base urllib functionality
54
import eventlet.green.urllib as urllib
55
```
56
57
### Data Structures and Queues
58
59
Green versions of queue and threading data structures.
60
61
```python { .api }
62
# Queue operations (thread-safe)
63
import eventlet.green.Queue as Queue
64
```
65
66
### Additional Green Modules
67
68
Other standard library modules with cooperative versions.
69
70
```python { .api }
71
# File I/O operations
72
import eventlet.green.io as io
73
# Regular expressions
74
import eventlet.green.re as re
75
# Database interfaces
76
import eventlet.green.dbm as dbm
77
# Compression utilities
78
import eventlet.green.gzip as gzip
79
# Archive utilities
80
import eventlet.green.tarfile as tarfile
81
import eventlet.green.zipfile as zipfile
82
```
83
84
## Usage Examples
85
86
### Green Socket Programming
87
88
```python
89
import eventlet
90
from eventlet.green import socket
91
import time
92
93
def tcp_server():
94
"""TCP server using green socket"""
95
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
96
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
97
server_sock.bind(('localhost', 8080))
98
server_sock.listen(5)
99
100
print("Green TCP server listening on localhost:8080")
101
102
while True:
103
client_sock, addr = server_sock.accept() # Cooperative accept
104
eventlet.spawn(handle_tcp_client, client_sock, addr)
105
106
def handle_tcp_client(sock, addr):
107
"""Handle TCP client connection"""
108
print(f"Client connected: {addr}")
109
try:
110
while True:
111
data = sock.recv(1024) # Cooperative recv
112
if not data:
113
break
114
sock.send(data) # Echo back - cooperative send
115
except Exception as e:
116
print(f"Client error: {e}")
117
finally:
118
sock.close()
119
print(f"Client disconnected: {addr}")
120
121
def tcp_client():
122
"""TCP client using green socket"""
123
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
124
125
try:
126
sock.connect(('localhost', 8080)) # Cooperative connect
127
128
for i in range(5):
129
message = f"Message {i}"
130
sock.send(message.encode()) # Cooperative send
131
response = sock.recv(1024) # Cooperative recv
132
print(f"Sent: {message}, Received: {response.decode()}")
133
time.sleep(1) # Cooperative sleep
134
135
except Exception as e:
136
print(f"Client error: {e}")
137
finally:
138
sock.close()
139
140
if __name__ == "__main__":
141
# Start server
142
eventlet.spawn(tcp_server)
143
144
# Wait a moment for server to start
145
eventlet.sleep(0.5)
146
147
# Start multiple clients concurrently
148
for i in range(3):
149
eventlet.spawn(tcp_client)
150
151
# Keep the program running
152
eventlet.sleep(10)
153
```
154
155
### Green HTTP Client
156
157
```python
158
import eventlet
159
from eventlet.green import urllib.request, urllib.parse, urllib.error
160
from eventlet.green.http import client as http_client
161
import json
162
163
def fetch_with_urllib(url):
164
"""Fetch URL using green urllib"""
165
try:
166
request = urllib.request.Request(url)
167
request.add_header('User-Agent', 'Eventlet Green Client')
168
169
# This will be cooperative I/O
170
response = urllib.request.urlopen(request, timeout=10)
171
172
data = response.read()
173
return {
174
'url': url,
175
'status': response.getcode(),
176
'headers': dict(response.headers),
177
'data': data.decode('utf-8')[:200] # First 200 chars
178
}
179
except urllib.error.URLError as e:
180
return {'url': url, 'error': str(e)}
181
182
def fetch_with_http_client(host, path):
183
"""Fetch using green HTTP client directly"""
184
try:
185
# Create green HTTP connection
186
conn = http_client.HTTPConnection(host, timeout=10)
187
188
# Make request - cooperative I/O
189
conn.request('GET', path, headers={
190
'User-Agent': 'Eventlet HTTP Client',
191
'Accept': 'application/json'
192
})
193
194
# Get response - cooperative I/O
195
response = conn.getresponse()
196
data = response.read()
197
198
conn.close()
199
200
return {
201
'host': host,
202
'path': path,
203
'status': response.status,
204
'reason': response.reason,
205
'headers': dict(response.getheaders()),
206
'data': data.decode('utf-8')
207
}
208
except Exception as e:
209
return {'host': host, 'path': path, 'error': str(e)}
210
211
def concurrent_http_requests():
212
"""Make multiple HTTP requests concurrently"""
213
214
# URLs for urllib testing
215
urllib_urls = [
216
'http://httpbin.org/json',
217
'http://httpbin.org/user-agent',
218
'http://httpbin.org/headers',
219
'http://example.com'
220
]
221
222
# Host/path pairs for HTTP client testing
223
http_requests = [
224
('httpbin.org', '/ip'),
225
('httpbin.org', '/delay/1'),
226
('httpbin.org', '/status/200'),
227
('example.com', '/')
228
]
229
230
print("Starting concurrent HTTP requests...")
231
232
# Spawn urllib requests
233
urllib_gts = []
234
for url in urllib_urls:
235
gt = eventlet.spawn(fetch_with_urllib, url)
236
urllib_gts.append(gt)
237
238
# Spawn HTTP client requests
239
http_gts = []
240
for host, path in http_requests:
241
gt = eventlet.spawn(fetch_with_http_client, host, path)
242
http_gts.append(gt)
243
244
# Collect urllib results
245
print("\nUrllib results:")
246
for gt in urllib_gts:
247
result = gt.wait()
248
if 'error' in result:
249
print(f"❌ {result['url']}: {result['error']}")
250
else:
251
print(f"✅ {result['url']}: {result['status']}")
252
253
# Collect HTTP client results
254
print("\nHTTP client results:")
255
for gt in http_gts:
256
result = gt.wait()
257
if 'error' in result:
258
print(f"❌ {result['host']}{result['path']}: {result['error']}")
259
else:
260
print(f"✅ {result['host']}{result['path']}: {result['status']}")
261
262
if __name__ == "__main__":
263
concurrent_http_requests()
264
```
265
266
### Green SSL/TLS Operations
267
268
```python
269
import eventlet
270
from eventlet.green import socket, ssl
271
import time
272
273
def ssl_server():
274
"""SSL server using green SSL"""
275
# Create server socket
276
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
277
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
278
server_sock.bind(('localhost', 8443))
279
server_sock.listen(5)
280
281
# Create SSL context
282
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
283
context.load_cert_chain('server.crt', 'server.key') # Requires cert files
284
285
print("Green SSL server listening on localhost:8443")
286
287
while True:
288
client_sock, addr = server_sock.accept() # Cooperative accept
289
290
try:
291
# Wrap with SSL - cooperative handshake
292
ssl_sock = context.wrap_socket(client_sock, server_side=True)
293
eventlet.spawn(handle_ssl_client, ssl_sock, addr)
294
except ssl.SSLError as e:
295
print(f"SSL handshake failed for {addr}: {e}")
296
client_sock.close()
297
298
def handle_ssl_client(ssl_sock, addr):
299
"""Handle SSL client connection"""
300
print(f"SSL client connected: {addr}")
301
302
try:
303
# Get client certificate info
304
peer_cert = ssl_sock.getpeercert()
305
cipher = ssl_sock.cipher()
306
307
print(f"Client {addr} - Cipher: {cipher[0] if cipher else 'None'}")
308
309
while True:
310
# Cooperative SSL read
311
data = ssl_sock.recv(1024)
312
if not data:
313
break
314
315
# Cooperative SSL write
316
ssl_sock.send(b"SSL Echo: " + data)
317
318
except Exception as e:
319
print(f"SSL client error: {e}")
320
finally:
321
ssl_sock.close()
322
print(f"SSL client disconnected: {addr}")
323
324
def ssl_client():
325
"""SSL client using green SSL"""
326
try:
327
# Create socket and SSL context
328
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
329
330
context = ssl.create_default_context()
331
context.check_hostname = False # For self-signed certs
332
context.verify_mode = ssl.CERT_NONE # For testing
333
334
# Connect and wrap with SSL
335
sock.connect(('localhost', 8443)) # Cooperative connect
336
ssl_sock = context.wrap_socket(sock) # Cooperative handshake
337
338
print(f"SSL connected - Cipher: {ssl_sock.cipher()[0]}")
339
340
# Send messages
341
for i in range(3):
342
message = f"Secure message {i}"
343
ssl_sock.send(message.encode()) # Cooperative SSL send
344
response = ssl_sock.recv(1024) # Cooperative SSL recv
345
print(f"Sent: {message}, Received: {response.decode()}")
346
eventlet.sleep(1)
347
348
except Exception as e:
349
print(f"SSL client error: {e}")
350
finally:
351
ssl_sock.close()
352
353
# Note: This example requires SSL certificate files
354
# Generate test certificates with:
355
# openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes
356
```
357
358
### Green Threading and Synchronization
359
360
```python
361
import eventlet
362
from eventlet.green import threading, time
363
from eventlet.green import Queue
364
365
def green_threading_example():
366
"""Example using green threading primitives"""
367
368
# Green threading objects work with eventlet
369
lock = threading.Lock()
370
condition = threading.Condition(lock)
371
shared_data = {'counter': 0, 'items': []}
372
373
def producer(name, count):
374
"""Producer that adds items"""
375
for i in range(count):
376
with condition:
377
shared_data['counter'] += 1
378
shared_data['items'].append(f"{name}-item-{i}")
379
print(f"Producer {name} added item {i} (total: {shared_data['counter']})")
380
condition.notify_all() # Wake up consumers
381
382
time.sleep(0.1) # Cooperative sleep
383
384
def consumer(name):
385
"""Consumer that processes items"""
386
processed = 0
387
388
while processed < 5: # Process 5 items
389
with condition:
390
while not shared_data['items']:
391
print(f"Consumer {name} waiting for items...")
392
condition.wait() # Cooperative wait
393
394
if shared_data['items']:
395
item = shared_data['items'].pop(0)
396
shared_data['counter'] -= 1
397
processed += 1
398
print(f"Consumer {name} processed {item} (remaining: {shared_data['counter']})")
399
400
time.sleep(0.2) # Simulate processing time
401
402
print(f"Consumer {name} finished")
403
404
# Start producers and consumers
405
eventlet.spawn(producer, "P1", 3)
406
eventlet.spawn(producer, "P2", 4)
407
eventlet.spawn(consumer, "C1")
408
eventlet.spawn(consumer, "C2")
409
410
# Wait for completion
411
eventlet.sleep(5)
412
413
def green_queue_example():
414
"""Example using green Queue"""
415
416
q = Queue.Queue(maxsize=5) # Bounded queue
417
418
def producer(name, items):
419
"""Add items to queue"""
420
for item in items:
421
print(f"Producer {name} adding {item}")
422
q.put(item) # Cooperative put (may block if queue full)
423
time.sleep(0.1)
424
425
print(f"Producer {name} finished")
426
427
def consumer(name):
428
"""Get items from queue"""
429
items_processed = 0
430
431
while items_processed < 5:
432
try:
433
# Cooperative get with timeout
434
item = q.get(timeout=2.0)
435
print(f"Consumer {name} got {item}")
436
q.task_done() # Mark task as done
437
items_processed += 1
438
time.sleep(0.2) # Simulate processing
439
except Queue.Empty:
440
print(f"Consumer {name} timed out waiting")
441
break
442
443
print(f"Consumer {name} finished")
444
445
# Start producers
446
eventlet.spawn(producer, "P1", ["apple", "banana", "cherry"])
447
eventlet.spawn(producer, "P2", ["orange", "grape", "kiwi"])
448
449
# Start consumers
450
eventlet.spawn(consumer, "C1")
451
eventlet.spawn(consumer, "C2")
452
453
# Wait for all tasks to complete
454
eventlet.spawn(lambda: q.join()) # Wait for all items processed
455
eventlet.sleep(5)
456
457
if __name__ == "__main__":
458
print("=== Green Threading Example ===")
459
green_threading_example()
460
461
print("\n=== Green Queue Example ===")
462
green_queue_example()
463
```
464
465
### Green Subprocess Management
466
467
```python
468
import eventlet
469
from eventlet.green import subprocess
470
import os
471
472
def run_green_subprocess():
473
"""Run subprocesses cooperatively"""
474
475
def run_command(name, command):
476
"""Run a command and capture output"""
477
try:
478
print(f"Starting {name}: {' '.join(command)}")
479
480
# Create subprocess - cooperative
481
process = subprocess.Popen(
482
command,
483
stdout=subprocess.PIPE,
484
stderr=subprocess.PIPE,
485
text=True
486
)
487
488
# Wait for completion - cooperative
489
stdout, stderr = process.communicate()
490
491
return {
492
'name': name,
493
'command': command,
494
'returncode': process.returncode,
495
'stdout': stdout.strip(),
496
'stderr': stderr.strip()
497
}
498
except Exception as e:
499
return {
500
'name': name,
501
'command': command,
502
'error': str(e)
503
}
504
505
# Commands to run concurrently
506
commands = [
507
("list_files", ["ls", "-la"]),
508
("current_date", ["date"]),
509
("system_info", ["uname", "-a"]),
510
("disk_usage", ["df", "-h"]),
511
("memory_info", ["free", "-h"])
512
]
513
514
print("Running multiple commands concurrently...")
515
516
# Start all commands concurrently
517
greenthreads = []
518
for name, command in commands:
519
gt = eventlet.spawn(run_command, name, command)
520
greenthreads.append(gt)
521
522
# Collect results
523
results = []
524
for gt in greenthreads:
525
result = gt.wait()
526
results.append(result)
527
528
# Display results
529
print("\nCommand Results:")
530
for result in results:
531
print(f"\n--- {result['name']} ---")
532
if 'error' in result:
533
print(f"Error: {result['error']}")
534
else:
535
print(f"Return code: {result['returncode']}")
536
if result['stdout']:
537
print(f"Output:\n{result['stdout']}")
538
if result['stderr']:
539
print(f"Error output:\n{result['stderr']}")
540
541
def interactive_subprocess():
542
"""Example of interactive subprocess communication"""
543
544
def chat_with_process():
545
"""Interactive communication with subprocess"""
546
try:
547
# Start a Python subprocess for interaction
548
process = subprocess.Popen(
549
['python3', '-c', '''
550
import sys
551
while True:
552
try:
553
line = input()
554
if line == "quit":
555
break
556
print(f"Echo: {line}")
557
sys.stdout.flush()
558
except EOFError:
559
break
560
'''],
561
stdin=subprocess.PIPE,
562
stdout=subprocess.PIPE,
563
stderr=subprocess.PIPE,
564
text=True,
565
bufsize=0 # Unbuffered
566
)
567
568
# Send messages and read responses
569
messages = ["Hello", "World", "How are you?", "quit"]
570
571
for message in messages:
572
print(f"Sending: {message}")
573
process.stdin.write(message + "\n")
574
process.stdin.flush()
575
576
if message == "quit":
577
break
578
579
# Read response - cooperative
580
response = process.stdout.readline().strip()
581
print(f"Received: {response}")
582
583
eventlet.sleep(0.5)
584
585
# Wait for process to finish
586
process.wait()
587
print("Interactive subprocess finished")
588
589
except Exception as e:
590
print(f"Interactive subprocess error: {e}")
591
592
eventlet.spawn(chat_with_process)
593
eventlet.sleep(5)
594
595
if __name__ == "__main__":
596
print("=== Green Subprocess Example ===")
597
run_green_subprocess()
598
599
print("\n=== Interactive Subprocess Example ===")
600
interactive_subprocess()
601
```
602
603
### Green File I/O Operations
604
605
```python
606
import eventlet
607
from eventlet.green import io, gzip, tarfile
608
import tempfile
609
import os
610
611
def green_file_operations():
612
"""File I/O operations using green modules"""
613
614
def read_large_file(filename):
615
"""Read a large file cooperatively"""
616
try:
617
with io.open(filename, 'r') as f:
618
line_count = 0
619
char_count = 0
620
621
# Read line by line - cooperative
622
for line in f:
623
line_count += 1
624
char_count += len(line)
625
626
# Yield occasionally for other greenthreads
627
if line_count % 1000 == 0:
628
eventlet.sleep(0)
629
630
return {
631
'filename': filename,
632
'lines': line_count,
633
'characters': char_count
634
}
635
except Exception as e:
636
return {'filename': filename, 'error': str(e)}
637
638
def compress_file(input_file, output_file):
639
"""Compress a file using green gzip"""
640
try:
641
with io.open(input_file, 'rb') as f_in:
642
with gzip.open(output_file, 'wb') as f_out:
643
# Copy data in chunks - cooperative
644
while True:
645
chunk = f_in.read(8192)
646
if not chunk:
647
break
648
f_out.write(chunk)
649
eventlet.sleep(0) # Yield for other greenthreads
650
651
# Get compression ratio
652
orig_size = os.path.getsize(input_file)
653
comp_size = os.path.getsize(output_file)
654
ratio = (orig_size - comp_size) / orig_size * 100
655
656
return {
657
'input_file': input_file,
658
'output_file': output_file,
659
'original_size': orig_size,
660
'compressed_size': comp_size,
661
'compression_ratio': ratio
662
}
663
except Exception as e:
664
return {'input_file': input_file, 'error': str(e)}
665
666
# Create test files
667
test_files = []
668
for i in range(3):
669
fd, filepath = tempfile.mkstemp(suffix=f'_test_{i}.txt')
670
with os.fdopen(fd, 'w') as f:
671
# Write test data
672
for j in range(1000):
673
f.write(f"Line {j} in file {i} - some test data here\n")
674
test_files.append(filepath)
675
676
try:
677
print("Processing files concurrently...")
678
679
# Read files concurrently
680
read_gts = []
681
for filepath in test_files:
682
gt = eventlet.spawn(read_large_file, filepath)
683
read_gts.append(gt)
684
685
# Compress files concurrently
686
compress_gts = []
687
for filepath in test_files:
688
output_file = filepath + '.gz'
689
gt = eventlet.spawn(compress_file, filepath, output_file)
690
compress_gts.append(gt)
691
692
# Collect read results
693
print("\nFile reading results:")
694
for gt in read_gts:
695
result = gt.wait()
696
if 'error' in result:
697
print(f"❌ {result['filename']}: {result['error']}")
698
else:
699
print(f"✅ {result['filename']}: {result['lines']} lines, {result['characters']} chars")
700
701
# Collect compression results
702
print("\nFile compression results:")
703
for gt in compress_gts:
704
result = gt.wait()
705
if 'error' in result:
706
print(f"❌ {result['input_file']}: {result['error']}")
707
else:
708
print(f"✅ {result['input_file']}: {result['compression_ratio']:.1f}% compression")
709
710
finally:
711
# Clean up test files
712
for filepath in test_files:
713
try:
714
os.unlink(filepath)
715
if os.path.exists(filepath + '.gz'):
716
os.unlink(filepath + '.gz')
717
except:
718
pass
719
720
if __name__ == "__main__":
721
green_file_operations()
722
```
723
724
## Module Availability
725
726
The `eventlet.green` package includes cooperative versions of most Python standard library modules. Key modules include:
727
728
- **Core I/O**: `socket`, `ssl`, `select`, `io`
729
- **HTTP/Web**: `http.client`, `http.server`, `urllib.*`
730
- **Concurrency**: `threading`, `subprocess`, `Queue`
731
- **System**: `os`, `time`, `signal`
732
- **Data**: `dbm`, `gzip`, `tarfile`, `zipfile`
733
- **Network**: `ftplib`, `smtplib`, `poplib`, `imaplib`
734
735
Each green module provides the same API as its standard library counterpart but with cooperative I/O that works with eventlet's event loop.