Skip to content

Commit 67d97a1

Browse files
committed
Added thread locals and subprocess guides.
1 parent 588e36e commit 67d97a1

File tree

2 files changed

+297
-12
lines changed

2 files changed

+297
-12
lines changed

index.html

Lines changed: 154 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,13 @@ <h3 class="author">
6565
<li><a href="#groups-and-pools">Groups and Pools</a></li>
6666
<li><a href="#locks-and-semaphores">Locks and Semaphores</a></li>
6767
<li><a href="#thread-locals">Thread Locals</a></li>
68+
<li><a href="#subprocess">Subprocess</a></li>
6869
<li><a href="#actors">Actors</a></li>
6970
</ul>
7071
</li>
7172
<li><a href="#real-world-applications">Real World Applications</a><ul>
7273
<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>
7475
<li><a href="#wsgi-servers">WSGI Servers</a></li>
7576
<li><a href="#streaming-servers">Streaming Servers</a></li>
7677
<li><a href="#long-polling">Long Polling</a></li>
@@ -249,16 +250,16 @@ <h2 id="synchronous-asynchronous-execution">Synchronous &amp; Asynchronous Execu
249250
Task 8 done
250251
Task 9 done
251252
Asynchronous:
252-
Task 0 done
253-
Task 6 done
254253
Task 1 done
255-
Task 9 done
256-
Task 3 done
257-
Task 4 done
258254
Task 2 done
259-
Task 7 done
260255
Task 5 done
256+
Task 7 done
257+
Task 9 done
261258
Task 8 done
259+
Task 0 done
260+
Task 3 done
261+
Task 4 done
262+
Task 6 done
262263
</pre></code></p>
263264
<p>In the synchronous case all the tasks are run sequentially,
264265
which results in the main programming <em>blocking</em> (
@@ -895,11 +896,11 @@ <h2 id="groups-and-pools">Groups and Pools</h2>
895896
<p></code>
896897
<pre><code class="python">
897898
Size of group 3
898-
Hello from Greenlet 34519152
899+
Hello from Greenlet 41900624
899900
Size of group 3
900-
Hello from Greenlet 34518512
901+
Hello from Greenlet 41900944
901902
Size of group 3
902-
Hello from Greenlet 34519472
903+
Hello from Greenlet 41899024
903904
Ordered
904905
('task', 0)
905906
('task', 1)
@@ -1011,6 +1012,148 @@ <h2 id="locks-and-semaphores">Locks and Semaphores</h2>
10111012
ensure that resources are only in use at one time in the context
10121013
of a program.</p>
10131014
<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>
10141157
<h2 id="actors">Actors</h2>
10151158
<p>The actor model is a higher level concurrency model popularized
10161159
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>
11461289
Switched to Server for 9
11471290
Switched to Client for 9
11481291
</pre></code></p>
1149-
<h2 id="simple-telnet-servers">Simple Telnet Servers</h2>
1292+
<h2 id="simple-servers">Simple Servers</h2>
11501293
<pre>
11511294
<code class="python">
11521295
# On Unix: Access with ``$ nc 127.0.0.1 5000``

tutorial.md

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,148 @@ of a program.
833833

834834
## Thread Locals
835835

836+
Gevnet also allows you to specify data which is local the
837+
greenlet context. Internally this is implemented as a global
838+
lookup which addresses a private namespace keyed by the
839+
greenlet's ``getcurrent()`` value.
840+
841+
[[[cog
842+
import gevent
843+
from gevent.local import local
844+
845+
stash = local()
846+
847+
def f1():
848+
stash.x = 1
849+
print(stash.x)
850+
851+
def f2():
852+
stash.y = 2
853+
print(stash.y)
854+
855+
try:
856+
stash.x
857+
except AttributeError:
858+
print("x is not local to f2")
859+
860+
g1 = gevent.spawn(f1)
861+
g2 = gevent.spawn(f2)
862+
863+
gevent.joinall([g1, g2])
864+
]]]
865+
[[[end]]]
866+
867+
Many web framework thats integrate with gevent store HTTP session
868+
objects inside of gevent thread locals. For example using the
869+
Werkzeug utility library and its proxy object we can create
870+
Flask style request objects.
871+
872+
<pre>
873+
<code class="python">from gevent.local import local
874+
from werkzeug.local import LocalProxy
875+
from werkzeug.wrappers import Request
876+
from contextlib import contextmanager
877+
878+
from gevent.wsgi import WSGIServer
879+
880+
_requests = local()
881+
request = LocalProxy(lambda: _requests.request)
882+
883+
@contextmanager
884+
def sessionmanager(environ):
885+
_requests.request = Request(environ)
886+
yield
887+
_requests.request = None
888+
889+
def logic():
890+
return "Hello " + request.remote_addr
891+
892+
def application(environ, start_response):
893+
status = '200 OK'
894+
895+
with sessionmanager(environ):
896+
body = logic()
897+
898+
headers = [
899+
('Content-Type', 'text/html')
900+
]
901+
902+
start_response(status, headers)
903+
return [body]
904+
905+
WSGIServer(('', 8000), application).serve_forever()
906+
907+
908+
<code>
909+
</pre>
910+
911+
Flask's system is more a bit sophisticated than this example, but the
912+
idea of using thread locals as local session storage is nontheless the
913+
same.
914+
915+
## Subprocess
916+
917+
As of Gevent 1.0, support has been added for cooperative waiting
918+
on subprocess.
919+
920+
<pre>
921+
<code class="python">import gevent
922+
from gevent.subprocess import Popen, PIPE
923+
924+
# Uses a green pipe which is cooperative
925+
sub = Popen(['uname'], stdout=PIPE)
926+
read_output = gevent.spawn(sub.stdout.read)
927+
928+
output = read_output.join()
929+
print(output.value)
930+
<code>
931+
</pre>
932+
933+
<pre>
934+
<code class="python">Linux
935+
<code>
936+
</pre>
937+
938+
Many people also want to use gevent and multiprocessing together. This
939+
can be done as most multiprocessing objects expose the underlying file
940+
descriptors.
941+
942+
[[[cog
943+
import gevent
944+
from multiprocessing import Process, Pipe
945+
from gevent.socket import wait_read, wait_write
946+
947+
# To Process
948+
a, b = Pipe()
949+
950+
# From Process
951+
c, d = Pipe()
952+
953+
def relay():
954+
for i in xrange(10):
955+
msg = b.recv()
956+
c.send(msg + " in " + str(i))
957+
958+
def put_msg():
959+
for i in xrange(10):
960+
wait_write(a.fileno())
961+
a.send('hi')
962+
963+
def get_msg():
964+
for i in xrange(10):
965+
wait_read(d.fileno())
966+
print(d.recv())
967+
968+
if __name__ == '__main__':
969+
proc = Process(target=relay)
970+
proc.start()
971+
972+
g1 = gevent.spawn(get_msg)
973+
g2 = gevent.spawn(put_msg)
974+
gevent.joinall([g1, g2], timeout=1)
975+
]]]
976+
[[[end]]]
977+
836978
## Actors
837979

838980
The actor model is a higher level concurrency model popularized
@@ -957,7 +1099,7 @@ gevent.joinall([publisher, client])
9571099
]]]
9581100
[[[end]]]
9591101

960-
## Simple Telnet Servers
1102+
## Simple Servers
9611103

9621104
<pre>
9631105
<code class="python">

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy