From 7ffdf408c4501cb045365816ad60ed02f82a056c Mon Sep 17 00:00:00 2001
From: Balthazar Rouberol import gevent.monkey
gevent.monkey.patch_socket()
@@ -225,9 +225,9 @@ asynchronous()
## Determinism
As mentioned previously, greenlets are deterministic. Given the same
-configuration of greenlets and the same set of inputs and they always
-produce the same output. For example lets spread a task across a
-multiprocessing pool compared to a gevent pool.
+configuration of greenlets and the same set of inputs, they always
+produce the same output. For example, let's spread a task across a
+multiprocessing pool and compare its results to the one of a gevent pool.
-Or with a context manager in a ``with`` statement.
+They can also be used with a context manager, in a ``with`` statement.
@@ -276,15 +276,14 @@ concurrency", they still can experience some of the same problems
that POSIX threads and processes experience.
The perennial problem involved with concurrency is known as a
-*race condition*. Simply put is when two concurrent threads
+*race condition*. Simply put, a race condition occurs when two concurrent threads
/ processes depend on some shared resource but also attempt to
-modify this value. This results in resources whose values become
+modify this value. This results in resources which values become
time-dependent on the execution order. This is a problem, and in
general one should very much try to avoid race conditions since
-they result program behavior which is globally
-non-deterministic.
+they result in a globally non-deterministic program behavior.
-The best approach to this is to simply avoid all global state all
+The best approach to this is to simply avoid all global state at all
times. Global state and import-time side effects will always come
back to bite you!
@@ -457,7 +456,7 @@ except Timeout:
-Flask's system is more a bit sophisticated than this example, but the
-idea of using thread locals as local session storage is nontheless the
+Flask's system is a bit more sophisticated than this example, but the
+idea of using thread locals as local session storage is nonetheless the
same.
## Subprocess
From c46220f468fbb02908c2a91256534ec57e261b1d Mon Sep 17 00:00:00 2001
From: Balthazar Rouberol import gevent
@@ -566,7 +565,7 @@ of our gevent stack.
This lets us integrate libraries that would not normally work with
gevent without ever writing a single line of code. While monkey-patching
-is still evil, in this case it is a "usefull evil".
+is still evil, in this case it is a "useful evil".
# Data Structures
@@ -684,7 +683,7 @@ either ``gevent.queue.Empty`` or
``gevent.queue.Full`` in the operation is not possible.
In this example we have the boss running simultaneously to the
-workers and have a restriction on the Queue that it can contain no
+workers and have a restriction on the Queue preventing it from containing
more than three elements. This restriction means that the ``put``
operation will block until there is space on the queue.
Conversely the ``get`` operation will block if there are
@@ -759,10 +758,9 @@ group.join()
]]]
[[[end]]]
-This is very usefull for managing groups of asynchronous tasks
-that.
+This is very useful for managing groups of asynchronous tasks.
-As mentioned above Group also provides an API for dispatching
+As mentioned above, ``Group`` also provides an API for dispatching
jobs to grouped greenlets and collecting their results in various
ways.
@@ -890,8 +888,8 @@ of a program.
## Thread Locals
-Gevnet also allows you to specify data which is local the
-greenlet context. Internally this is implemented as a global
+Gevent also allows you to specify data which is local to the
+greenlet context. Internally, this is implemented as a global
lookup which addresses a private namespace keyed by the
greenlet's ``getcurrent()`` value.
@@ -965,8 +963,8 @@ WSGIServer(('', 8000), application).serve_forever()
The internal state of a greenlet is generally a time-dependent +The internal state of a greenlet is generally a time-dependent parameter. There are a number of flags on greenlets which let -you monitor the state of the thread
+you monitor the state of the thread: -- ``started`` -- Boolean, indicates whether the Greenlet has been started. -- ``ready()`` -- Boolean, indicates whether the Greenlet has halted -- ``successful()`` -- Boolean, indicates whether the Greenlet has halted and not thrown an exception -- ``value`` -- arbitrary, the value returned by the Greenlet -- ``exception`` -- exception, uncaught exception instance thrown inside the greenlet +- ``started`` -- Boolean, indicates whether the Greenlet has been started +- ``ready()`` -- Boolean, indicates whether the Greenlet has halted +- ``successful()`` -- Boolean, indicates whether the Greenlet has halted and not thrown an exception +- ``value`` -- arbitrary, the value returned by the Greenlet +- ``exception`` -- exception, uncaught exception instance thrown inside the greenlet [[[cog import gevent From e3e0e6e90a5dfb7c96b547b76d622c4592c8a551 Mon Sep 17 00:00:00 2001 From: Balthazar RouberolIn the synchronous case all the tasks are run sequentially, which results in the main programming blocking ( @@ -281,9 +281,9 @@
A more common use case, fetching data from a server
-asynchronously, the runtime of fetch() will differ between
-requests given the load on the remote server.
In a more common use case, asynchronously fetching data from a server,
+the runtime of fetch() will differ between
+requests, depending on the load on the remote server at the time of the request.
import gevent.monkey gevent.monkey.patch_socket() @@ -320,9 +320,9 @@-Synchronous & Asynchronous Execu
Determinism
As mentioned previously, greenlets are deterministic. Given the same -configuration of greenlets and the same set of inputs and they always -produce the same output. For example lets spread a task across a -multiprocessing pool compared to a gevent pool.
+configuration of greenlets and the same set of inputs, they always +produce the same output. For example, let's spread a task across a +multiprocessing pool and compare its results to the one of a gevent pool.import time @@ -369,14 +369,13 @@Determinism
concurrency", they still can experience some of the same problems that POSIX threads and processes experience.The perennial problem involved with concurrency is known as a -race condition. Simply put is when two concurrent threads +race condition. Simply put, a race condition occurs when two concurrent threads / processes depend on some shared resource but also attempt to -modify this value. This results in resources whose values become +modify this value. This results in resources which values become time-dependent on the execution order. This is a problem, and in general one should very much try to avoid race conditions since -they result program behavior which is globally -non-deterministic.
-The best approach to this is to simply avoid all global state all +they result in a globally non-deterministic program behavior.
+The best approach to this is to simply avoid all global state at all times. Global state and import-time side effects will always come back to bite you!
Spawning Greenlets
@@ -445,17 +444,16 @@Spawning Greenlets
Greenlet State
Like any other segment of code, Greenlets can fail in various ways. A greenlet may fail to throw an exception, fail to halt or -consume too many system resources.
+consume too many system resources.The internal state of a greenlet is generally a time-dependent parameter. There are a number of flags on greenlets which let -you monitor the state of the thread
- +you monitor the state of the thread:-
- -
started-- Boolean, indicates whether the Greenlet has been started.- -
ready()-- Boolean, indicates whether the Greenlet has halted- -
successful()-- Boolean, indicates whether the Greenlet has halted and not thrown an exception- -
value-- arbitrary, the value returned by the Greenlet- +
exception-- exception, uncaught exception instance thrown inside the greenlet- +
started-- Boolean, indicates whether the Greenlet has been started- +
ready()-- Boolean, indicates whether the Greenlet has halted- +
successful()-- Boolean, indicates whether the Greenlet has halted and not thrown an exception- +
value-- arbitrary, the value returned by the Greenletexception-- exception, uncaught exception instance thrown inside the greenlet-import gevent @@ -556,7 +554,7 @@Timeouts
Or with a context manager in a
+withstatement.They can also be used with a context manager, in a
withstatement.@@ -664,7 +662,7 @@import gevent from gevent import Timeout @@ -642,8 +640,8 @@Monkeypatching
After monkey patch class 'gevent.socket.socket' -After monkey patch built-in function select +After monkey patch function select at 0x1924de8Monkeypatching
of our gevent stack.This lets us integrate libraries that would not normally work with gevent without ever writing a single line of code. While monkey-patching -is still evil, in this case it is a "usefull evil".
+is still evil, in this case it is a "useful evil".Data Structures
Events
Events are a form of asynchronous communication between @@ -801,7 +799,7 @@
Queues
eithergevent.queue.Emptyorgevent.queue.Fullin the operation is not possible.In this example we have the boss running simultaneously to the -workers and have a restriction on the Queue that it can contain no +workers and have a restriction on the Queue preventing it from containing more than three elements. This restriction means that the
putoperation will block until there is space on the queue. Conversely thegetoperation will block if there are @@ -910,9 +908,8 @@Groups and Pools
fizz fizzThis is very usefull for managing groups of asynchronous tasks -that.
-As mentioned above Group also provides an API for dispatching +
This is very useful for managing groups of asynchronous tasks.
+As mentioned above,
Groupalso provides an API for dispatching jobs to grouped greenlets and collecting their results in various ways.@@ -949,11 +946,11 @@Groups and Pools
Size of group 3 -Hello from Greenlet 42121488 +Hello from Greenlet 20398800 Size of group 3 -Hello from Greenlet 42119248 +Hello from Greenlet 20399280 Size of group 3 -Hello from Greenlet 42120208 +Hello from Greenlet 20400240 Ordered ('task', 0) ('task', 1) @@ -969,7 +966,6 @@Groups and Pools
tasks in parallel.import gevent -from gevent import getcurrent from gevent.pool import Pool pool = Pool(2) @@ -1065,8 +1061,8 @@Locks and Semaphores
ensure that resources are only in use at one time in the context of a program.Thread Locals
-Gevnet also allows you to specify data which is local the -greenlet context. Internally this is implemented as a global +
Gevent also allows you to specify data which is local to the +greenlet context. Internally, this is implemented as a global lookup which addresses a private namespace keyed by the greenlet's
getcurrent()value.-@@ -1142,8 +1138,8 @@Thread Locals
Flask's system is more a bit sophisticated than this example, but the -idea of using thread locals as local session storage is nontheless the +
Flask's system is a bit more sophisticated than this example, but the +idea of using thread locals as local session storage is nonetheless the same.
Subprocess
As of Gevent 1.0, support has been added for cooperative waiting From dc7ac8778e3849324dd9b80a752dde559079aeec Mon Sep 17 00:00:00 2001 From: Stephen Diehl
Date: Sat, 8 Dec 2012 17:14:19 -0600 Subject: [PATCH 07/53] Merge 2nd PR. --- index.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 0c6e702..8e05272 100644 --- a/index.html +++ b/index.html @@ -124,7 +124,7 @@ Greenlets
are truly parallel.Synchronous & Asynchronous Execution
The core idea of concurrency is that a larger task can be broken down -into a collection of subtasks whose and scheduled to run simultaneously +into a collection of subtasks which are scheduled to run simultaneously or asynchronously, instead of one at a time or synchronously. A switch between the two subtasks is known as a context switch.
A context switch in gevent is done through yielding. In this case @@ -252,15 +252,15 @@
Synchronous & Asynchronous Execu Task 9 done Asynchronous: Task 0 done +Task 2 done Task 6 done -Task 3 done Task 7 done -Task 2 done Task 1 done -Task 8 done +Task 4 done +Task 3 done Task 5 done +Task 8 done Task 9 done -Task 4 done
In the synchronous case all the tasks are run sequentially, which results in the main programming blocking ( @@ -946,11 +946,11 @@
Groups and Pools
Size of group 3 -Hello from Greenlet 20398800 +Hello from Greenlet 14533328 Size of group 3 -Hello from Greenlet 20399280 +Hello from Greenlet 14533808 Size of group 3 -Hello from Greenlet 20400240 +Hello from Greenlet 14534768 Ordered ('task', 0) ('task', 1) From 39d3be09e341c0a660587b379fea6a0da2f6e5fb Mon Sep 17 00:00:00 2001 From: Jan-Philip GehrckeDate: Fri, 25 Jan 2013 12:16:41 +0100 Subject: [PATCH 08/53] Adjust CSS: enable bulleted lists in text body, do not change TOC style. --- base.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/base.css b/base.css index 6b5f6e0..8cfbb6d 100644 --- a/base.css +++ b/base.css @@ -36,8 +36,6 @@ display: block; } body { line-height: 1; } - ol, ul { - list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, @@ -102,8 +100,7 @@ /* #Lists ================================================== */ - ul, ol { margin-bottom: 20px; } - ul { list-style: none outside; } + ul, ol { margin-bottom: 20px; padding-left: 20px; } ol { list-style: decimal; } ol, ul.square, ul.circle, ul.disc { margin-left: 30px; } ul.square { list-style: square outside; } @@ -116,6 +113,11 @@ li { line-height: 18px; margin-bottom: 12px; } ul.large li { line-height: 21px; } li p { line-height: 21px; } + #sidebar ul { + list-style: none outside none; + padding-left: 0; + } + /* #Images ================================================== */ From 0d2a62f766214d9855c12623366856edbc35cbd6 Mon Sep 17 00:00:00 2001 From: Jan-Philip Gehrcke Date: Fri, 25 Jan 2013 14:04:01 +0100 Subject: [PATCH 09/53] Consolidate section about multiprocessing. --- tutorial.md | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tutorial.md b/tutorial.md index 321dd79..a53ec3a 100644 --- a/tutorial.md +++ b/tutorial.md @@ -968,8 +968,9 @@ same. ## Subprocess -As of Gevent 1.0, support has been added for cooperative waiting -on subprocess. +As of gevent 1.0, ``gevent.subprocess`` -- a patched version of Python's +``subprocess`` module -- has been added. It supports cooperative waiting on +subprocesses. import gevent @@ -981,19 +982,24 @@ read_output = gevent.spawn(sub.stdout.read) output = read_output.join() print(output.value) -+-Many people also want to use gevent and multiprocessing together. This -can be done as most multiprocessing objects expose the underlying file -descriptors. +Many people also want to use ``gevent`` and ``multiprocessing`` together. One of +the most obvious challenges is that inter-process communication provided by +``multiprocessing`` is not cooperative by default. Since +``multiprocessing.Connection``-based objects (such as ``Pipe``) expose their +underlying file descriptors, ``gevent.socket.wait_read`` and ``wait_write`` can +be used to cooperatively wait for ready-to-read/ready-to-write events before +actually reading/writing: -[[[cog +Linux -+++ +Note, however, that the combination of ``multiprocessing`` and gevent brings +along certain OS-dependent pitfalls, among others: + +* After [forking](http://linux.die.net/man/2/fork) on POSIX-compliant systems +gevent's state in the child is ill-posed. One side effect is that greenlets +spawned before ``multiprocessing.Process`` creation run in both, parent and +child process. +* ``a.send()`` in ``put_msg()`` above might still block the calling thread +non-cooperatively: a ready-to-write event only ensures that one byte can be +written. The underlying buffer might be full before the attempted write is +complete. +* The ``wait_write()`` / ``wait_read()``-based approach as indicated above does +not work on Windows (``IOError: 3 is not a socket (files are not supported)``), +because Windows cannot watch pipes for events. + +The Python package [gipc](http://pypi.python.org/pypi/gipc) overcomes these +challenges for you in a largely transparent fashion on both, POSIX-compliant and +Windows systems. It provides gevent-aware ``multiprocessing.Process``-based +child processes and gevent-cooperative inter-process communication based on +pipes. ## Actors From aa7f770bbcdf628832f2dce5fd556475136c1f98 Mon Sep 17 00:00:00 2001 From: Jan-Philip Gehrckeimport gevent from multiprocessing import Process, Pipe from gevent.socket import wait_read, wait_write @@ -1026,8 +1032,29 @@ if __name__ == '__main__': g1 = gevent.spawn(get_msg) g2 = gevent.spawn(put_msg) gevent.joinall([g1, g2], timeout=1) -]]] -[[[end]]] ++Date: Fri, 25 Jan 2013 14:34:32 +0100 Subject: [PATCH 10/53] Change cooperative subprocess example. --- tutorial.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tutorial.md b/tutorial.md index 321dd79..3520adc 100644 --- a/tutorial.md +++ b/tutorial.md @@ -972,20 +972,30 @@ As of Gevent 1.0, support has been added for cooperative waiting on subprocess. -import gevent ++import gevent from gevent.subprocess import Popen, PIPE -# Uses a green pipe which is cooperative -sub = Popen(['uname'], stdout=PIPE) -read_output = gevent.spawn(sub.stdout.read) - -output = read_output.join() -print(output.value) -+def cron(): + while True: + print "cron" + gevent.sleep(0.2) + +g = gevent.spawn(cron) +sub = Popen(['sleep 1; uname'], stdout=PIPE, shell=True) +out, err = sub.communicate() +g.kill() +print out.rstrip()-From d344edb21baab81e11e699cc17bb012d9a0f55ec Mon Sep 17 00:00:00 2001 From: Stephen DiehlLinux ++cron +cron +cron +cron +cron +LinuxDate: Fri, 25 Jan 2013 10:44:06 -0600 Subject: [PATCH 11/53] Merge branch 'master', remote-tracking branch 'origin' From 58120ab51564c47c67a2418c3bdba5a73ae424a4 Mon Sep 17 00:00:00 2001 From: Stephen Diehl Date: Fri, 25 Jan 2013 10:49:54 -0600 Subject: [PATCH 12/53] Rebuild per PR from @jgehrcke --- index.html | 64 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/index.html b/index.html index 8e05272..18c0023 100644 --- a/index.html +++ b/index.html @@ -251,16 +251,16 @@ Synchronous & Asynchronous Execu Task 8 done Task 9 done Asynchronous: -Task 0 done -Task 2 done +Task 8 done +Task 5 done Task 6 done +Task 3 done +Task 9 done +Task 2 done Task 7 done +Task 0 done Task 1 done Task 4 done -Task 3 done -Task 5 done -Task 8 done -Task 9 done
In the synchronous case all the tasks are run sequentially, which results in the main programming blocking ( @@ -946,11 +946,11 @@
Groups and Pools
Size of group 3 -Hello from Greenlet 14533328 +Hello from Greenlet 22721552 Size of group 3 -Hello from Greenlet 14533808 +Hello from Greenlet 22722672 Size of group 3 -Hello from Greenlet 14534768 +Hello from Greenlet 22724432 Ordered ('task', 0) ('task', 1) @@ -1142,8 +1142,9 @@+Thread Locals
idea of using thread locals as local session storage is nonetheless the same.Subprocess
-As of Gevent 1.0, support has been added for cooperative waiting -on subprocess.
+As of gevent 1.0,
gevent.subprocess-- a patched version of Python's +subprocessmodule -- has been added. It supports cooperative waiting on +subprocesses.import gevent from gevent.subprocess import Popen, PIPE @@ -1154,18 +1155,23 @@Subprocess
output = read_output.join() print(output.value) -+-Linux -+Many people also want to use gevent and multiprocessing together. This -can be done as most multiprocessing objects expose the underlying file -descriptors.
-+-Many people also want to use
+geventandmultiprocessingtogether. One of +the most obvious challenges is that inter-process communication provided by +multiprocessingis not cooperative by default. Since +multiprocessing.Connection-based objects (such asPipe) expose their +underlying file descriptors,gevent.socket.wait_readandwait_writecan +be used to cooperatively wait for ready-to-read/ready-to-write events before +actually reading/writing:+-import gevent from multiprocessing import Process, Pipe from gevent.socket import wait_read, wait_write @@ -1198,11 +1204,29 @@Subprocess
g1 = gevent.spawn(get_msg) g2 = gevent.spawn(put_msg) gevent.joinall([g1, g2], timeout=1) +-Note, however, that the combination of
+multiprocessingand gevent brings +along certain OS-dependent pitfalls, among others:
multiprocessing.Process creation run in both, parent and
+child process.a.send() in put_msg() above might still block the calling thread
+non-cooperatively: a ready-to-write event only ensures that one byte can be
+written. The underlying buffer might be full before the attempted write is
+complete.wait_write() / wait_read()-based approach as indicated above does
+not work on Windows (IOError: 3 is not a socket (files are not supported)),
+because Windows cannot watch pipes for events.The Python package gipc overcomes these
+challenges for you in a largely transparent fashion on both, POSIX-compliant and
+Windows systems. It provides gevent-aware multiprocessing.Process-based
+child processes and gevent-cooperative inter-process communication based on
+pipes.
The actor model is a higher level concurrency model popularized
by the language Erlang. In short the main idea is that you have a
From 484d85afb749950660a43a963fe216d723aaf15d Mon Sep 17 00:00:00 2001
From: Stephen Diehl Synchronous & Asynchronous Execu
Task 8 done
Task 9 done
Asynchronous:
-Task 8 done
-Task 5 done
-Task 6 done
-Task 3 done
-Task 9 done
+Task 1 done
Task 2 done
Task 7 done
+Task 6 done
+Task 5 done
Task 0 done
-Task 1 done
+Task 3 done
+Task 8 done
+Task 9 done
Task 4 done
In the synchronous case all the tasks are run sequentially, @@ -946,11 +946,11 @@
But regardless, performance on Gevent servers is phenomenal compared to other Python servers. libev is a very vetted technology and its derivative servers are known to perform well at scale. -To benchmark, try Apache Benchmark ``ab`` or see this -[Benchmark of Python WSGI Servers](http://nichol.as/benchmark-of-python-web-servers) +To benchmark, try Apache Benchmark ``ab`` or see this +[Benchmark of Python WSGI Servers](http://nichol.as/benchmark-of-python-web-servers) for comparison with other servers.Size of group 3 -Hello from Greenlet 22721552 +Hello from Greenlet 10769424 Size of group 3 -Hello from Greenlet 22722672 +Hello from Greenlet 10770544 Size of group 3 -Hello from Greenlet 22724432 +Hello from Greenlet 10772304 Ordered ('task', 0) ('task', 1) @@ -1146,21 +1146,31 @@Subprocess
subprocessmodule -- has been added. It supports cooperative waiting on subprocesses.-import gevent ++import gevent from gevent.subprocess import Popen, PIPE -# Uses a green pipe which is cooperative -sub = Popen(['uname'], stdout=PIPE) -read_output = gevent.spawn(sub.stdout.read) - -output = read_output.join() -print(output.value) -+def cron(): + while True: + print "cron" + gevent.sleep(0.2) + +g = gevent.spawn(cron) +sub = Popen(['sleep 1; uname'], stdout=PIPE, shell=True) +out, err = sub.communicate() +g.kill() +print out.rstrip()-Linux -++cron +cron +cron +cron +cron +Linux +Many people also want to use
geventandmultiprocessingtogether. One of From 30abf6b001868016cd23234e9c0a4b285542ef6a Mon Sep 17 00:00:00 2001 From: Matthijs van der VleutenDate: Wed, 6 Mar 2013 10:54:27 +0100 Subject: [PATCH 14/53] Fix a typo --- tutorial.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tutorial.md b/tutorial.md index 22a8a17..81779f2 100644 --- a/tutorial.md +++ b/tutorial.md @@ -514,10 +514,10 @@ except Timeout: Alas we come to dark corners of Gevent. I've avoided mentioning monkey patching up until now to try and motivate the powerful -coroutine patterns but the time has come to discuss the dark arts -of monkey-patching. If you noticed above we invoked the commnad +coroutine patterns, but the time has come to discuss the dark arts +of monkey-patching. If you noticed above we invoked the command ``monkey.patch_socket()``. This is a purely side-effectful command to -modify the standard library's socket library +modify the standard library's socket library. import socket From 8b71cb4a4232b6fbcb164822296740b3daa0e9b2 Mon Sep 17 00:00:00 2001 From: Simon HaywardDate: Sun, 10 Mar 2013 11:10:05 +0000 Subject: [PATCH 15/53] Typo in comment --- tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial.md b/tutorial.md index 81779f2..5940fe5 100644 --- a/tutorial.md +++ b/tutorial.md @@ -308,7 +308,7 @@ def foo(message, n): # foo thread1 = Greenlet.spawn(foo, "Hello", 1) -# Wrapper for creating and runing a new Greenlet from the named +# Wrapper for creating and running a new Greenlet from the named # function foo, with the passed arguments thread2 = gevent.spawn(foo, "I live!", 2) From 976f18e922219200f090966c43b26438b9f5a019 Mon Sep 17 00:00:00 2001 From: Alexander James Phillips Date: Wed, 5 Jun 2013 16:43:37 +0100 Subject: [PATCH 16/53] remove trailing whitespace --- index.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index f16245c..b1b8adb 100644 --- a/index.html +++ b/index.html @@ -90,7 +90,7 @@ Introduction
your existing concurrency problems and start writing asynchronous applications today.Contributors
-In chronological order of contribution: +
In chronological order of contribution: Stephen Diehl Jérémy Bethmont sww @@ -268,7 +268,7 @@
Synchronous & Asynchronous Execu while each task executes.
The important parts of the program are the
gevent.spawnwhich wraps up the given function -inside of a Greenlet thread. The list of initialized greenlets +inside of a Greenlet thread. The list of initialized greenlets are stored in the arraythreadswhich is passed to thegevent.joinallfunction which blocks the current program to run all the given greenlets. The execution will step @@ -397,7 +397,7 @@Spawning Greenlets
# foo thread1 = Greenlet.spawn(foo, "Hello", 1) -# Wrapper for creating and runing a new Greenlet from the named +# Wrapper for creating and runing a new Greenlet from the named # function foo, with the passed arguments thread2 = gevent.spawn(foo, "I live!", 2) @@ -698,7 +698,7 @@Events
A extension of the Event object is the AsyncResult which allows you to send a value along with the wakeup call. This is -sometimes called a future or a deferred, since it holds a +sometimes called a future or a deferred, since it holds a reference to a future value that can be set on an arbitrary time schedule.
@@ -794,7 +794,7 @@Queues
Queues can also block on either
putorgetas the need arises.Each of the
@@ -1375,7 +1375,7 @@putandgetoperations has a non-blocking -counterpart,put_nowaitand +counterpart,put_nowaitandget_nowaitwhich will not block, but instead raise eithergevent.queue.Emptyorgevent.queue.Fullin the operation is not possible.Gevent ZeroMQ
Simple Servers
+-# On Unix: Access with ``$ nc 127.0.0.1 5000`` +# On Unix: Access with ``$ nc 127.0.0.1 5000`` # On Window: Access with ``$ telnet 127.0.0.1 5000`` from gevent.server import StreamServer @@ -1469,8 +1469,8 @@-Streaming Servers
But regardless, performance on Gevent servers is phenomenal compared to other Python servers. libev is a very vetted technology and its derivative servers are known to perform well at scale.
-To benchmark, try Apache Benchmark
abor see this -Benchmark of Python WSGI Servers +To benchmark, try Apache Benchmark
abor see this +Benchmark of Python WSGI Servers for comparison with other servers.Using pywsgi we can however write our handler as a generator and yield the result chunk by chunk. @@ -1303,20 +1303,20 @@ def application(environ, start_response): WSGIServer(('', 8000), application).serve_forever()$ ab -n 10000 -c 100 http://127.0.0.1:8000/ From 9be98060948fe9459ee3dbe873377fbfcfe89133 Mon Sep 17 00:00:00 2001 From: Alexander James PhillipsDate: Wed, 5 Jun 2013 16:47:08 +0100 Subject: [PATCH 17/53] minor spelling mistake and grammar --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index b1b8adb..f7de00c 100644 --- a/index.html +++ b/index.html @@ -797,8 +797,8 @@ Queues
counterpart,put_nowaitandget_nowaitwhich will not block, but instead raise eithergevent.queue.Emptyor -gevent.queue.Fullin the operation is not possible. -In this example we have the boss running simultaneously to the +
+gevent.queue.Fullif the operation is not possible.In the example below we have the boss running simultaneously to the workers and have a restriction on the Queue preventing it from containing more than three elements. This restriction means that the
putoperation will block until there is space on the queue. From dccfea210f34a45fe2cc34bf954693a4e597eafc Mon Sep 17 00:00:00 2001 From: Ramiro MoralesDate: Thu, 18 Jul 2013 15:50:19 -0300 Subject: [PATCH 18/53] Update tutorial.md --- tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial.md b/tutorial.md index 5940fe5..b55df5d 100644 --- a/tutorial.md +++ b/tutorial.md @@ -117,7 +117,7 @@ def gr2(): print('Ended Polling: ', tic()) def gr3(): - print("Hey lets do some stuff while the greenlets poll, at", tic()) + print("Hey lets do some stuff while the greenlets poll, ", tic()) gevent.sleep(1) gevent.joinall([ From 38a20c7f89ed77116ec70121f87b344bbed1b248 Mon Sep 17 00:00:00 2001 From: Philip Damra Date: Fri, 19 Jul 2013 09:07:41 -0400 Subject: [PATCH 19/53] Update tutorial.md The example illustrating the use of gevent.event.Event mistakenly used AsyncResult --- tutorial.md | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/tutorial.md b/tutorial.md index b55df5d..15c51a3 100644 --- a/tutorial.md +++ b/tutorial.md @@ -576,29 +576,40 @@ Greenlets. From 10f9bcffec69f7426a7b888e56f62b58ad0535c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Marques=20Vieira?=import gevent -from gevent.event import AsyncResult +from gevent.event import Event -a = AsyncResult() +''' +Illustrates the use of events +''' -def setter(): - """ - After 3 seconds set wake all threads waiting on the value of - a. - """ - gevent.sleep(3) - a.set() -def waiter(): - """ - After 3 seconds the get call will unblock. - """ - a.get() # blocking - print 'I live!' +evt = Event() -gevent.joinall([ - gevent.spawn(setter), - gevent.spawn(waiter), -]) +def setter(): + '''After 3 seconds, wake all threads waiting on the value of evt''' + print('A: Hey wait for me, I have to do something') + gevent.sleep(3) + print("Ok, I'm done") + evt.set() + + +def waiter(): + '''After 3 seconds the get call will unblock''' + print("I'll wait for you") + evt.wait() # blocking + print("It's about time") + +def main(): + gevent.joinall([ + gevent.spawn(setter), + gevent.spawn(waiter), + gevent.spawn(waiter), + gevent.spawn(waiter), + gevent.spawn(waiter), + gevent.spawn(waiter) + ]) + +if __name__ == '__main__': main()Date: Fri, 19 Jul 2013 16:35:41 +0100 Subject: [PATCH 20/53] Trimmed trailing whitespace --- tutorial.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tutorial.md b/tutorial.md index 15c51a3..56a3306 100644 --- a/tutorial.md +++ b/tutorial.md @@ -11,7 +11,7 @@ applications today. ### Contributors -In chronological order of contribution: +In chronological order of contribution: [Stephen Diehl](http://www.stephendiehl.com) [Jérémy Bethmont](https://github.com/jerem) [sww](https://github.com/sww) @@ -41,7 +41,7 @@ This page is also [available in Japanese](http://methane.github.com/gevent-tutor The primary pattern used in gevent is the Greenlet, a lightweight coroutine provided to Python as a C extension module. Greenlets all run inside of the OS process for the main -program but are scheduled cooperatively. +program but are scheduled cooperatively. > Only one greenlet is ever running at any given time. @@ -169,7 +169,7 @@ while each task executes. The important parts of the program are the ``gevent.spawn`` which wraps up the given function -inside of a Greenlet thread. The list of initialized greenlets +inside of a Greenlet thread. The list of initialized greenlets are stored in the array ``threads`` which is passed to the ``gevent.joinall`` function which blocks the current program to run all the given greenlets. The execution will step @@ -308,7 +308,7 @@ def foo(message, n): # foo thread1 = Greenlet.spawn(foo, "Hello", 1) -# Wrapper for creating and running a new Greenlet from the named +# Wrapper for creating and running a new Greenlet from the named # function foo, with the passed arguments thread2 = gevent.spawn(foo, "I live!", 2) @@ -591,14 +591,14 @@ def setter(): gevent.sleep(3) print("Ok, I'm done") evt.set() - - + + def waiter(): '''After 3 seconds the get call will unblock''' print("I'll wait for you") evt.wait() # blocking print("It's about time") - + def main(): gevent.joinall([ gevent.spawn(setter), @@ -616,7 +616,7 @@ if __name__ == '__main__': main() A extension of the Event object is the AsyncResult which allows you to send a value along with the wakeup call. This is -sometimes called a future or a deferred, since it holds a +sometimes called a future or a deferred, since it holds a reference to a future value that can be set on an arbitrary time schedule. @@ -685,10 +685,10 @@ gevent.joinall([ ]]] [[[end]]] -Queues can also block on either ``put`` or ``get`` as the need arises. +Queues can also block on either ``put`` or ``get`` as the need arises. Each of the ``put`` and ``get`` operations has a non-blocking -counterpart, ``put_nowait`` and +counterpart, ``put_nowait`` and ``get_nowait`` which will not block, but instead raise either ``gevent.queue.Empty`` or ``gevent.queue.Full`` in the operation is not possible. @@ -1084,7 +1084,7 @@ by the language Erlang. In short the main idea is that you have a collection of independent Actors which have an inbox from which they receive messages from other Actors. The main loop inside the Actor iterates through its messages and takes action according to -its desired behavior. +its desired behavior. Gevent does not have a primitive Actor type, but we can define one very simply using a Queue inside of a subclassed Greenlet. @@ -1153,7 +1153,7 @@ gevent.joinall([ping, pong]) [ZeroMQ](http://www.zeromq.org/) is described by its authors as "a socket library that acts as a concurrency framework". It is a very powerful messaging layer for building concurrent and -distributed applications. +distributed applications. ZeroMQ provides a variety of socket primitives, the simplest of which being a Request-Response socket pair. A socket has two @@ -1205,8 +1205,8 @@ gevent.joinall([publisher, client]) +-# On Unix: Access with ``$ nc 127.0.0.1 5000`` -# On Window: Access with ``$ telnet 127.0.0.1 5000`` +# On Unix: Access with ``$ nc 127.0.0.1 5000`` +# On Window: Access with ``$ telnet 127.0.0.1 5000`` from gevent.server import StreamServer @@ -1231,7 +1231,7 @@ Henceforth called ``wsgi`` and ``pywsgi``: In earlier versions of gevent before 1.0.x, gevent used libevent instead of libev. Libevent included a fast HTTP server which was -used by gevent's ``wsgi`` server. +used by gevent's ``wsgi`` server. In gevent 1.0.x there is no http server included. Instead ``gevent.wsgi`` is now an alias for the pure Python server in @@ -1281,7 +1281,7 @@ def application(environ, start_response): WSGIServer(('', 8000), application).serve_forever()-
$ ab -n 10000 -c 100 http://127.0.0.1:8000/
-
+
## Long Polling
From afaaf45393ef7cde0b467c316704de068a03f77e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Marques=20Vieira?=
The primary pattern used in gevent is the Greenlet, a lightweight coroutine provided to Python as a C extension module. Greenlets all run inside of the OS process for the main -program but are scheduled cooperatively.
+program but are scheduled cooperatively.@@ -188,7 +188,7 @@Only one greenlet is ever running at any given time.
Started Polling: at 0.0 seconds
Started Polling: at 0.0 seconds
-Hey lets do some stuff while the greenlets poll, at at 0.0 seconds
+Hey lets do some stuff while the greenlets poll, at 0.0 seconds
Ended Polling: at 2.0 seconds
Ended Polling: at 2.0 seconds
@@ -251,16 +251,16 @@ In the synchronous case all the tasks are run sequentially, which results in the main programming blocking ( @@ -397,7 +397,7 @@
Alas we come to dark corners of Gevent. I've avoided mentioning
monkey patching up until now to try and motivate the powerful
-coroutine patterns but the time has come to discuss the dark arts
-of monkey-patching. If you noticed above we invoked the commnad
+coroutine patterns, but the time has come to discuss the dark arts
+of monkey-patching. If you noticed above we invoked the command
monkey.patch_socket(). This is a purely side-effectful command to
-modify the standard library's socket library
import socket
print( socket.socket )
@@ -669,29 +669,38 @@ Events
Greenlets.
import gevent
-from gevent.event import AsyncResult
+from gevent.event import Event
-a = AsyncResult()
+'''
+Illustrates the use of events
+'''
+
+evt = Event()
def setter():
- """
- After 3 seconds set wake all threads waiting on the value of
- a.
- """
+ '''After 3 seconds, wake all threads waiting on the value of evt'''
+ print('A: Hey wait for me, I have to do something')
gevent.sleep(3)
- a.set()
+ print("Ok, I'm done")
+ evt.set()
def waiter():
- """
- After 3 seconds the get call will unblock.
- """
- a.get() # blocking
- print 'I live!'
-
-gevent.joinall([
- gevent.spawn(setter),
- gevent.spawn(waiter),
-])
+ '''After 3 seconds the get call will unblock'''
+ print("I'll wait for you")
+ evt.wait() # blocking
+ print("It's about time")
+
+def main():
+ gevent.joinall([
+ gevent.spawn(setter),
+ gevent.spawn(waiter),
+ gevent.spawn(waiter),
+ gevent.spawn(waiter),
+ gevent.spawn(waiter),
+ gevent.spawn(waiter)
+ ])
+
+if __name__ == '__main__': main()
@@ -792,13 +801,13 @@ Queues
Quitting time!
Quitting time!
-Queues can also block on either put or get as the need arises.
Queues can also block on either put or get as the need arises.
Each of the put and get operations has a non-blocking
counterpart, put_nowait and
get_nowait which will not block, but instead raise
either gevent.queue.Empty or
-gevent.queue.Full if the operation is not possible.
In the example below we have the boss running simultaneously to the
+gevent.queue.Full in the operation is not possible.
In this example we have the boss running simultaneously to the
workers and have a restriction on the Queue preventing it from containing
more than three elements. This restriction means that the put
operation will block until there is space on the queue.
@@ -946,11 +955,11 @@
Size of group 3
-Hello from Greenlet 10769424
+Hello from Greenlet 157878268
Size of group 3
-Hello from Greenlet 10770544
+Hello from Greenlet 157878828
Size of group 3
-Hello from Greenlet 10772304
+Hello from Greenlet 157878908
Ordered
('task', 0)
('task', 1)
@@ -1243,7 +1252,7 @@ Actors
collection of independent Actors which have an inbox from which
they receive messages from other Actors. The main loop inside the
Actor iterates through its messages and takes action according to
-its desired behavior.
+its desired behavior.
Gevent does not have a primitive Actor type, but we can define
one very simply using a Queue inside of a subclassed Greenlet.
@@ -1306,7 +1315,7 @@ Gevent ZeroMQ
ZeroMQ is described by its authors as
"a socket library that acts as a concurrency framework". It is a
very powerful messaging layer for building concurrent and
-distributed applications.
+distributed applications.
ZeroMQ provides a variety of socket primitives, the simplest of
which being a Request-Response socket pair. A socket has two
methods of interest send and recv, both of which are
@@ -1400,7 +1409,7 @@
WSGI Servers
In earlier versions of gevent before 1.0.x, gevent used libevent
instead of libev. Libevent included a fast HTTP server which was
-used by gevent's wsgi server.
+used by gevent's wsgi server.
In gevent 1.0.x there is no http server included. Instead
gevent.wsgi is now an alias for the pure Python server in
gevent.pywsgi.
From 88054b3f58bc591fffbb65980ca62c3f2f229d68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Marques=20Vieira?=
Date: Fri, 19 Jul 2013 16:06:17 +0100
Subject: [PATCH 22/53] Fix timing typo
---
index.html | 4 ++--
tutorial.md | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/index.html b/index.html
index 8bc255b..7b62a72 100644
--- a/index.html
+++ b/index.html
@@ -277,8 +277,8 @@ Synchronous & Asynchronous Execu
the async case is essentially random and that the total execution
time in the async case is much less than the sync case. In fact
the maximum time for the synchronous case to complete is when
-each tasks pauses for 2 seconds resulting in a 20 seconds for the
-whole queue. In the async case the maximum runtime is roughly 2
+each tasks pauses for 0.002 seconds resulting in a 0.02 seconds for the
+whole queue. In the async case the maximum runtime is roughly 0.002
seconds since none of the tasks block the execution of the
others.
In a more common use case, asynchronously fetching data from a server,
diff --git a/tutorial.md b/tutorial.md
index 56a3306..e82d3ae 100644
--- a/tutorial.md
+++ b/tutorial.md
@@ -179,8 +179,8 @@ The important fact to notice is that the order of execution in
the async case is essentially random and that the total execution
time in the async case is much less than the sync case. In fact
the maximum time for the synchronous case to complete is when
-each tasks pauses for 2 seconds resulting in a 20 seconds for the
-whole queue. In the async case the maximum runtime is roughly 2
+each tasks pauses for 0.002 seconds resulting in a 0.02 seconds for the
+whole queue. In the async case the maximum runtime is roughly 0.002
seconds since none of the tasks block the execution of the
others.
From 8a101433c5164abe2ab30d26c620f4ce429067b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Marques=20Vieira?=
Date: Fri, 19 Jul 2013 16:27:04 +0100
Subject: [PATCH 23/53] Add parenthesis to all prints for consistency
---
index.html | 38 +++++++++++++++++++-------------------
tutorial.md | 38 +++++++++++++++++++-------------------
2 files changed, 38 insertions(+), 38 deletions(-)
diff --git a/index.html b/index.html
index 7b62a72..f9612c9 100644
--- a/index.html
+++ b/index.html
@@ -297,7 +297,7 @@ Synchronous & Asynchronous Execu
json_result = json.loads(result)
datetime = json_result['datetime']
- print 'Process ', pid, datetime
+ print('Process', pid, datetime)
return json_result['datetime']
def synchronous():
@@ -310,10 +310,10 @@ Synchronous & Asynchronous Execu
threads.append(gevent.spawn(fetch, i))
gevent.joinall(threads)
-print 'Synchronous:'
+print('Synchronous:')
synchronous()
-print 'Asynchronous:'
+print('Asynchronous:')
asynchronous()
@@ -341,7 +341,7 @@
import socket
-print( socket.socket )
+print(socket.socket)
-print "After monkey patch"
+print("After monkey patch")
from gevent import monkey
monkey.patch_socket()
-print( socket.socket )
+print(socket.socket)
import select
-print select.select
+print(select.select)
monkey.patch_select()
-print "After monkey patch"
-print( select.select )
+print("After monkey patch")
+print(select.select)
@@ -727,7 +727,7 @@ @@ -1289,13 +1289,13 @@@@ -247,7 +247,7 @@ run2 = [a for a in p.imap_unordered(echo, xrange(10))] run3 = [a for a in p.imap_unordered(echo, xrange(10))] run4 = [a for a in p.imap_unordered(echo, xrange(10))] -print( run1 == run2 == run3 == run4 ) +print(run1 == run2 == run3 == run4) # Deterministic Gevent Pool @@ -259,7 +259,7 @@ run2 = [a for a in p.imap_unordered(echo, xrange(10))] run3 = [a for a in p.imap_unordered(echo, xrange(10))] run4 = [a for a in p.imap_unordered(echo, xrange(10))] -print( run1 == run2 == run3 == run4 ) +print(run1 == run2 == run3 == run4) @@ -451,7 +451,7 @@ def wait(): try: gevent.spawn(wait).join() except Timeout: - print 'Could not complete' + print('Could not complete') @@ -521,18 +521,18 @@ modify the standard library's socket library.Actors
class Pinger(Actor): def receive(self, message): - print message + print(message) pong.inbox.put('ping') gevent.sleep(0) class Ponger(Actor): def receive(self, message): - print message + print(message) ping.inbox.put('pong') gevent.sleep(0) @@ -1624,7 +1624,7 @@Chat Server
def add(self, message): for user in self.users: - print user + print(user) user.queue.put_nowait(message) self.messages.append(message) @@ -1653,7 +1653,7 @@Chat Server
active_room = rooms[room] active_room.subscribe(user) - print 'subscribe', active_room, user + print('subscribe', active_room, user) messages = active_room.backlog() diff --git a/tutorial.md b/tutorial.md index e82d3ae..f43d031 100644 --- a/tutorial.md +++ b/tutorial.md @@ -201,7 +201,7 @@ def fetch(pid): json_result = json.loads(result) datetime = json_result['datetime'] - print 'Process ', pid, datetime + print('Process', pid, datetime) return json_result['datetime'] def synchronous(): @@ -214,10 +214,10 @@ def asynchronous(): threads.append(gevent.spawn(fetch, i)) gevent.joinall(threads) -print 'Synchronous:' +print('Synchronous:') synchronous() -print 'Asynchronous:' +print('Asynchronous:') asynchronous()
import socket
-print( socket.socket )
+print(socket.socket)
-print "After monkey patch"
+print("After monkey patch")
from gevent import monkey
monkey.patch_socket()
-print( socket.socket )
+print(socket.socket)
import select
-print select.select
+print(select.select)
monkey.patch_select()
-print "After monkey patch"
-print( select.select )
+print("After monkey patch")
+print(select.select)
@@ -637,7 +637,7 @@ def waiter():
After 3 seconds the get call will unblock after the setter
puts a value into the AsyncResult.
"""
- print a.get()
+ print(a.get())
gevent.joinall([
gevent.spawn(setter),
@@ -990,14 +990,14 @@ from gevent.subprocess import Popen, PIPE
def cron():
while True:
- print "cron"
+ print("cron")
gevent.sleep(0.2)
g = gevent.spawn(cron)
sub = Popen(['sleep 1; uname'], stdout=PIPE, shell=True)
out, err = sub.communicate()
g.kill()
-print out.rstrip()
+print(out.rstrip())
@@ -1125,13 +1125,13 @@ from gevent import Greenlet
class Pinger(Actor):
def receive(self, message):
- print message
+ print(message)
pong.inbox.put('ping')
gevent.sleep(0)
class Ponger(Actor):
def receive(self, message):
- print message
+ print(message)
ping.inbox.put('pong')
gevent.sleep(0)
@@ -1466,7 +1466,7 @@ class Room(object):
def add(self, message):
for user in self.users:
- print user
+ print(user)
user.queue.put_nowait(message)
self.messages.append(message)
@@ -1495,7 +1495,7 @@ def join(room, uid):
active_room = rooms[room]
active_room.subscribe(user)
- print 'subscribe', active_room, user
+ print('subscribe', active_room, user)
messages = active_room.backlog()
From ff3deb4e8215f7aea95dfd3c101135dbc8245dcf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Marques=20Vieira?=
Date: Fri, 19 Jul 2013 16:35:20 +0100
Subject: [PATCH 24/53] Avoid multiple arguments in prints so they all work in
Python 2 and 3
---
index.html | 70 ++++++++++++++++++++++++++---------------------------
tutorial.md | 24 +++++++++---------
2 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/index.html b/index.html
index f9612c9..9fc5283 100644
--- a/index.html
+++ b/index.html
@@ -177,18 +177,18 @@ Synchronous & Asynchronous Execu
def gr1():
# Busy waits for a second, but we don't want to stick around...
- print('Started Polling: ', tic())
+ print('Started Polling: %s' % tic())
select.select([], [], [], 2)
- print('Ended Polling: ', tic())
+ print('Ended Polling: %s' % tic())
def gr2():
# Busy waits for a second, but we don't want to stick around...
- print('Started Polling: ', tic())
+ print('Started Polling: %s' % tic())
select.select([], [], [], 2)
- print('Ended Polling: ', tic())
+ print('Ended Polling: %s' % tic())
def gr3():
- print("Hey lets do some stuff while the greenlets poll, ", tic())
+ print("Hey lets do some stuff while the greenlets poll, %s" % tic())
gevent.sleep(1)
gevent.joinall([
@@ -200,11 +200,11 @@ Synchronous & Asynchronous Execu
-Started Polling: at 0.0 seconds
-Started Polling: at 0.0 seconds
-Hey lets do some stuff while the greenlets poll, at 0.0 seconds
-Ended Polling: at 2.0 seconds
-Ended Polling: at 2.0 seconds
+Started Polling: at 0.0 seconds
+Started Polling: at 0.0 seconds
+Hey lets do some stuff while the greenlets poll, at 0.0 seconds
+Ended Polling: at 2.0 seconds
+Ended Polling: at 2.0 seconds
Another somewhat synthetic example defines a task function
which is non-deterministic
@@ -221,7 +221,7 @@
Synchronous & Asynchronous Execu
Some non-deterministic task
"""
gevent.sleep(random.randint(0,2)*0.001)
- print('Task', pid, 'done')
+ print('Task %s done' % pid)
def synchronous():
for i in range(1,10):
@@ -297,7 +297,7 @@ Synchronous & Asynchronous Execu
json_result = json.loads(result)
datetime = json_result['datetime']
- print('Process', pid, datetime)
+ print('Process %s: %s' % (pid, datetime))
return json_result['datetime']
def synchronous():
@@ -929,7 +929,7 @@ Groups and Pools
group = Group()
def hello_from(n):
- print('Size of group', len(group))
+ print('Size of group %s' % len(group))
print('Hello from Greenlet %s' % id(getcurrent()))
group.map(hello_from, xrange(3))
@@ -980,7 +980,7 @@ Groups and Pools
pool = Pool(2)
def hello_from(n):
- print('Size of pool', len(pool))
+ print('Size of pool %s' % len(pool))
pool.map(hello_from, xrange(3))
@@ -1338,7 +1338,7 @@
-Switched to Server for 1
-Switched to Client for 1
-Switched to Server for 2
-Switched to Client for 2
-Switched to Server for 3
-Switched to Client for 3
-Switched to Server for 4
-Switched to Client for 4
-Switched to Server for 5
-Switched to Client for 5
-Switched to Server for 6
-Switched to Client for 6
-Switched to Server for 7
-Switched to Client for 7
-Switched to Server for 8
-Switched to Client for 8
-Switched to Server for 9
-Switched to Client for 9
+Switched to Server for 1
+Switched to Client for 1
+Switched to Server for 2
+Switched to Client for 2
+Switched to Server for 3
+Switched to Client for 3
+Switched to Server for 4
+Switched to Client for 4
+Switched to Server for 5
+Switched to Client for 5
+Switched to Server for 6
+Switched to Client for 6
+Switched to Server for 7
+Switched to Client for 7
+Switched to Server for 8
+Switched to Client for 8
+Switched to Server for 9
+Switched to Client for 9
@@ -1653,7 +1653,7 @@-A extension of the Event object is the AsyncResult which +An extension of the Event object is the AsyncResult which allows you to send a value along with the wakeup call. This is sometimes called a future or a deferred, since it holds a reference to a future value that can be set on an arbitrary time @@ -691,7 +691,7 @@ Each of the ``put`` and ``get`` operations has a non-blocking counterpart, ``put_nowait`` and ``get_nowait`` which will not block, but instead raise either ``gevent.queue.Empty`` or -``gevent.queue.Full`` in the operation is not possible. +``gevent.queue.Full`` if the operation is not possible. In this example we have the boss running simultaneously to the workers and have a restriction on the Queue preventing it from containing @@ -929,10 +929,10 @@ gevent.joinall([g1, g2]) ]]] [[[end]]] -Many web framework thats integrate with gevent store HTTP session -objects inside of gevent thread locals. For example using the +Many web frameworks that use gevent store HTTP session +objects inside gevent thread locals. For example, using the Werkzeug utility library and its proxy object we can create -Flask style request objects. +Flask-style request objects.Chat Server
active_room = rooms[room] active_room.subscribe(user) - print('subscribe', active_room, user) + print('subscribe %s %s' % (active_room, user)) messages = active_room.backlog() diff --git a/tutorial.md b/tutorial.md index f43d031..290242c 100644 --- a/tutorial.md +++ b/tutorial.md @@ -106,18 +106,18 @@ tic = lambda: 'at %1.1f seconds' % (time.time() - start) def gr1(): # Busy waits for a second, but we don't want to stick around... - print('Started Polling: ', tic()) + print('Started Polling: %s' % tic()) select.select([], [], [], 2) - print('Ended Polling: ', tic()) + print('Ended Polling: %s' % tic()) def gr2(): # Busy waits for a second, but we don't want to stick around... - print('Started Polling: ', tic()) + print('Started Polling: %s' % tic()) select.select([], [], [], 2) - print('Ended Polling: ', tic()) + print('Ended Polling: %s' % tic()) def gr3(): - print("Hey lets do some stuff while the greenlets poll, ", tic()) + print("Hey lets do some stuff while the greenlets poll, %s" % tic()) gevent.sleep(1) gevent.joinall([ @@ -144,7 +144,7 @@ def task(pid): Some non-deterministic task """ gevent.sleep(random.randint(0,2)*0.001) - print('Task', pid, 'done') + print('Task %s done' % pid) def synchronous(): for i in range(1,10): @@ -201,7 +201,7 @@ def fetch(pid): json_result = json.loads(result) datetime = json_result['datetime'] - print('Process', pid, datetime) + print('Process %s: %s' % (pid, datetime)) return json_result['datetime'] def synchronous(): @@ -783,7 +783,7 @@ from gevent.pool import Group group = Group() def hello_from(n): - print('Size of group', len(group)) + print('Size of group %s' % len(group)) print('Hello from Greenlet %s' % id(getcurrent())) group.map(hello_from, xrange(3)) @@ -820,7 +820,7 @@ from gevent.pool import Pool pool = Pool(2) def hello_from(n): - print('Size of pool', len(pool)) + print('Size of pool %s' % len(pool)) pool.map(hello_from, xrange(3)) ]]] @@ -1178,7 +1178,7 @@ def server(): for request in range(1,10): server_socket.send("Hello") - print('Switched to Server for ', request) + print('Switched to Server for %s' % request) # Implicit context switch occurs here server_socket.recv() @@ -1189,7 +1189,7 @@ def client(): for request in range(1,10): client_socket.recv() - print('Switched to Client for ', request) + print('Switched to Client for %s' % request) # Implicit context switch occurs here client_socket.send("World") @@ -1495,7 +1495,7 @@ def join(room, uid): active_room = rooms[room] active_room.subscribe(user) - print('subscribe', active_room, user) + print('subscribe %s %s' % (active_room, user)) messages = active_room.backlog() From f1f614c92ad3d298390cb075a5f980578f7a9230 Mon Sep 17 00:00:00 2001 From: David XiaDate: Fri, 23 Aug 2013 00:30:28 -0400 Subject: [PATCH 25/53] Fixed some typos --- tutorial.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tutorial.md b/tutorial.md index 290242c..b4f327c 100644 --- a/tutorial.md +++ b/tutorial.md @@ -614,7 +614,7 @@ if __name__ == '__main__': main()
from gevent.local import local
From 9c4c172104962bc48c1da8cb37cec57a807e4fb9 Mon Sep 17 00:00:00 2001
From: satoru
Date: Sat, 28 Sep 2013 20:47:59 +0800
Subject: [PATCH 26/53] fix syntax
---
index.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.html b/index.html
index 9fc5283..dbd335f 100644
--- a/index.html
+++ b/index.html
@@ -741,8 +741,8 @@ Queues
Queues are ordered sets of data that have the usual put / get
operations but are written in a way such that they can be safely
manipulated across Greenlets.
-For example if one Greenlet grabs an item off of the queue, the
-same item will not grabbed by another Greenlet executing
+
For example, if one Greenlet grabs an item off of the queue, the
+same item will not be grabbed by another Greenlet executing
simultaneously.
import gevent
@@ -1686,4 +1686,4 @@ Chat Server