@@ -65,12 +65,13 @@ <h3 class="author">
65
65
< li > < a href ="#groups-and-pools "> Groups and Pools</ a > </ li >
66
66
< li > < a href ="#locks-and-semaphores "> Locks and Semaphores</ a > </ li >
67
67
< li > < a href ="#thread-locals "> Thread Locals</ a > </ li >
68
+ < li > < a href ="#subprocess "> Subprocess</ a > </ li >
68
69
< li > < a href ="#actors "> Actors</ a > </ li >
69
70
</ ul >
70
71
</ li >
71
72
< li > < a href ="#real-world-applications "> Real World Applications</ a > < ul >
72
73
< li > < a href ="#gevent-zeromq "> Gevent ZeroMQ</ a > </ li >
73
- < li > < a href ="#simple-telnet- servers "> Simple Telnet Servers</ a > </ li >
74
+ < li > < a href ="#simple-servers "> Simple Servers</ a > </ li >
74
75
< li > < a href ="#wsgi-servers "> WSGI Servers</ a > </ li >
75
76
< li > < a href ="#streaming-servers "> Streaming Servers</ a > </ li >
76
77
< li > < a href ="#long-polling "> Long Polling</ a > </ li >
@@ -249,16 +250,16 @@ <h2 id="synchronous-asynchronous-execution">Synchronous & Asynchronous Execu
249
250
Task 8 done
250
251
Task 9 done
251
252
Asynchronous:
252
- Task 0 done
253
- Task 6 done
254
253
Task 1 done
255
- Task 9 done
256
- Task 3 done
257
- Task 4 done
258
254
Task 2 done
259
- Task 7 done
260
255
Task 5 done
256
+ Task 7 done
257
+ Task 9 done
261
258
Task 8 done
259
+ Task 0 done
260
+ Task 3 done
261
+ Task 4 done
262
+ Task 6 done
262
263
</ pre > </ code > </ p >
263
264
< p > In the synchronous case all the tasks are run sequentially,
264
265
which results in the main programming < em > blocking</ em > (
@@ -895,11 +896,11 @@ <h2 id="groups-and-pools">Groups and Pools</h2>
895
896
< p > </ code >
896
897
< pre > < code class ="python ">
897
898
Size of group 3
898
- Hello from Greenlet 34519152
899
+ Hello from Greenlet 41900624
899
900
Size of group 3
900
- Hello from Greenlet 34518512
901
+ Hello from Greenlet 41900944
901
902
Size of group 3
902
- Hello from Greenlet 34519472
903
+ Hello from Greenlet 41899024
903
904
Ordered
904
905
('task', 0)
905
906
('task', 1)
@@ -1011,6 +1012,148 @@ <h2 id="locks-and-semaphores">Locks and Semaphores</h2>
1011
1012
ensure that resources are only in use at one time in the context
1012
1013
of a program.</ p >
1013
1014
< h2 id ="thread-locals "> Thread Locals</ h2 >
1015
+ < p > Gevnet also allows you to specify data which is local the
1016
+ greenlet context. Internally this is implemented as a global
1017
+ lookup which addresses a private namespace keyed by the
1018
+ greenlet's < code > getcurrent()</ code > value.</ p >
1019
+ < pre > < code class ="python ">
1020
+ import gevent
1021
+ from gevent.local import local
1022
+
1023
+ stash = local()
1024
+
1025
+ def f1():
1026
+ stash.x = 1
1027
+ print(stash.x)
1028
+
1029
+ def f2():
1030
+ stash.y = 2
1031
+ print(stash.y)
1032
+
1033
+ try:
1034
+ stash.x
1035
+ except AttributeError:
1036
+ print("x is not local to f2")
1037
+
1038
+ g1 = gevent.spawn(f1)
1039
+ g2 = gevent.spawn(f2)
1040
+
1041
+ gevent.joinall([g1, g2])
1042
+ </ pre >
1043
+
1044
+ < p > </ code >
1045
+ < pre > < code class ="python ">
1046
+ 1
1047
+ 2
1048
+ x is not local to f2
1049
+ </ pre > </ code > </ p >
1050
+ < p > Many web framework thats integrate with gevent store HTTP session
1051
+ objects inside of gevent thread locals. For example using the
1052
+ Werkzeug utility library and its proxy object we can create
1053
+ Flask style request objects.</ p >
1054
+ < pre >
1055
+ < code class ="python "> from gevent.local import local
1056
+ from werkzeug.local import LocalProxy
1057
+ from werkzeug.wrappers import Request
1058
+ from contextlib import contextmanager
1059
+
1060
+ from gevent.wsgi import WSGIServer
1061
+
1062
+ _requests = local()
1063
+ request = LocalProxy(lambda: _requests.request)
1064
+
1065
+ @contextmanager
1066
+ def sessionmanager(environ):
1067
+ _requests.request = Request(environ)
1068
+ yield
1069
+ _requests.request = None
1070
+
1071
+ def logic():
1072
+ return "Hello " + request.remote_addr
1073
+
1074
+ def application(environ, start_response):
1075
+ status = '200 OK'
1076
+
1077
+ with sessionmanager(environ):
1078
+ body = logic()
1079
+
1080
+ headers = [
1081
+ ('Content-Type', 'text/html')
1082
+ ]
1083
+
1084
+ start_response(status, headers)
1085
+ return [body]
1086
+
1087
+ WSGIServer(('', 8000), application).serve_forever()
1088
+
1089
+ < code >
1090
+ </ pre >
1091
+
1092
+ < p > Flask's system is more a bit sophisticated than this example, but the
1093
+ idea of using thread locals as local session storage is nontheless the
1094
+ same.</ p >
1095
+ < h2 id ="subprocess "> Subprocess</ h2 >
1096
+ < p > As of Gevent 1.0, support has been added for cooperative waiting
1097
+ on subprocess.</ p >
1098
+ < pre >
1099
+ < code class ="python "> import gevent
1100
+ from gevent.subprocess import Popen, PIPE
1101
+
1102
+ # Uses a green pipe which is cooperative
1103
+ sub = Popen(['uname'], stdout=PIPE)
1104
+ read_output = gevent.spawn(sub.stdout.read)
1105
+
1106
+ output = read_output.join()
1107
+ print(output.value)
1108
+ < code >
1109
+ </ pre >
1110
+
1111
+ < pre >
1112
+ < code class ="python "> Linux
1113
+ < code >
1114
+ </ pre >
1115
+
1116
+ < p > Many people also want to use gevent and multiprocessing together. This
1117
+ can be done as most multiprocessing objects expose the underlying file
1118
+ descriptors.</ p >
1119
+ < pre > < code class ="python ">
1120
+ import gevent
1121
+ from multiprocessing import Process, Pipe
1122
+ from gevent.socket import wait_read, wait_write
1123
+
1124
+ # To Process
1125
+ a, b = Pipe()
1126
+
1127
+ # From Process
1128
+ c, d = Pipe()
1129
+
1130
+ def relay():
1131
+ for i in xrange(10):
1132
+ msg = b.recv()
1133
+ c.send(msg + " in " + str(i))
1134
+
1135
+ def put_msg():
1136
+ for i in xrange(10):
1137
+ wait_write(a.fileno())
1138
+ a.send('hi')
1139
+
1140
+ def get_msg():
1141
+ for i in xrange(10):
1142
+ wait_read(d.fileno())
1143
+ print(d.recv())
1144
+
1145
+ if __name__ == '__main__':
1146
+ proc = Process(target=relay)
1147
+ proc.start()
1148
+
1149
+ g1 = gevent.spawn(get_msg)
1150
+ g2 = gevent.spawn(put_msg)
1151
+ gevent.joinall([g1, g2], timeout=1)
1152
+ </ pre >
1153
+
1154
+ < p > </ code >
1155
+ < pre > < code class ="python ">
1156
+ </ pre > </ code > </ p >
1014
1157
< h2 id ="actors "> Actors</ h2 >
1015
1158
< p > The actor model is a higher level concurrency model popularized
1016
1159
by the language Erlang. In short the main idea is that you have a
@@ -1146,7 +1289,7 @@ <h2 id="gevent-zeromq">Gevent ZeroMQ</h2>
1146
1289
Switched to Server for 9
1147
1290
Switched to Client for 9
1148
1291
</ pre > </ code > </ p >
1149
- < h2 id ="simple-telnet- servers "> Simple Telnet Servers</ h2 >
1292
+ < h2 id ="simple-servers "> Simple Servers</ h2 >
1150
1293
< pre >
1151
1294
< code class ="python ">
1152
1295
# On Unix: Access with ``$ nc 127.0.0.1 5000``
0 commit comments