diff --git a/doc/basic_usage.rst b/doc/basic_usage.rst index db242b3..f33a7aa 100644 --- a/doc/basic_usage.rst +++ b/doc/basic_usage.rst @@ -24,7 +24,7 @@ Greenthread Spawn .. function:: eventlet.spawn_n(func, *args, **kw) - The same as :func:`spawn`, but it's not possible to retrieve the return value. This makes execution faster. See :func:`spawn_n ` for more details. + The same as :func:`spawn`, but it's not possible to know how the function terminated (i.e. no return value or exceptions). This makes execution faster. See :func:`spawn_n ` for more details. .. function:: eventlet.spawn_after(seconds, func, *args, **kw) diff --git a/doc/real_index.html b/doc/real_index.html index 62ca706..98d4927 100644 --- a/doc/real_index.html +++ b/doc/real_index.html @@ -68,29 +68,22 @@ easy_install eventlet

Web Crawler ExampleΒΆ

This is a simple web “crawler” that fetches a bunch of urls using a coroutine pool. It has as much concurrency (i.e. pages being fetched simultaneously) as coroutines in the pool.

+
urls = ["http://www.google.com/intl/en_ALL/images/logo.gif",
-       "http://wiki.secondlife.com/w/images/secondlife.jpg",
-       "http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif"]
+     "https://wiki.secondlife.com/w/images/secondlife.jpg",
+     "http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif"]
 
-import time
-from eventlet import coros
-
-# this imports a special version of the urllib2 module that uses non-blocking IO
+import eventlet
 from eventlet.green import urllib2
 
 def fetch(url):
-    print "%s fetching %s" % (time.asctime(), url)
-    data = urllib2.urlopen(url)
-    print "%s fetched %s" % (time.asctime(), data)
 
-pool = coros.CoroutinePool(max_size=4)
-waiters = []
-for url in urls:
-    waiters.append(pool.execute(fetch, url))
+  return urllib2.urlopen(url).read()
 
-# wait for all the coroutines to come back before exiting the process
-for waiter in waiters:
-    waiter.wait()
+pool = eventlet.GreenPool()
+
+for body in pool.imap(fetch, urls):
+  print "got body", len(body)
 

Stats

diff --git a/eventlet/greenpool.py b/eventlet/greenpool.py index 4027ab8..afac07d 100644 --- a/eventlet/greenpool.py +++ b/eventlet/greenpool.py @@ -9,7 +9,7 @@ from eventlet.support import greenlets as greenlet __all__ = ['GreenPool', 'GreenPile'] -DEBUG = False +DEBUG = True class GreenPool(object): """The GreenPool class is a pool of green threads. diff --git a/eventlet/greenthread.py b/eventlet/greenthread.py index 7bcaf93..65cb045 100644 --- a/eventlet/greenthread.py +++ b/eventlet/greenthread.py @@ -54,9 +54,15 @@ def _main_wrapper(func, args, kwargs): def spawn_n(func, *args, **kwargs): - """Same as :func:`spawn`, but returns a ``greenlet`` object from which it is - not possible to retrieve the results. This is faster than :func:`spawn`; - it is fastest if there are no keyword arguments.""" + """Same as :func:`spawn`, but returns a ``greenlet`` object from + which it is not possible to retrieve either a return value or + whether it raised any exceptions. This is faster than + :func:`spawn`; it is fastest if there are no keyword arguments. + + If an exception is raised in the function, spawn_n prints a stack + trace; the print can be disabled by calling + :func:`eventlet.debug.hub_exceptions` with False. + """ return _spawn_n(0, func, args, kwargs)[1] diff --git a/tests/tpool_test.py b/tests/tpool_test.py index f1c5624..9dc3ced 100644 --- a/tests/tpool_test.py +++ b/tests/tpool_test.py @@ -133,6 +133,7 @@ class TestTpool(LimitedTestCase): @skip_with_pyevent def test_wrap_iterator(self): + self.reset_timeout(2) prox = tpool.Proxy(xrange(10)) result = [] for i in prox: @@ -152,7 +153,10 @@ class TestTpool(LimitedTestCase): def tick(): for i in xrange(20000): counter[0]+=1 - eventlet.sleep() + if counter[0] % 20 == 0: + eventlet.sleep(0.0001) + else: + eventlet.sleep() gt = eventlet.spawn(tick) previtem = 0 @@ -160,9 +164,9 @@ class TestTpool(LimitedTestCase): self.assert_(item >= previtem) # make sure the tick happened at least a few times so that we know # that our iterations in foo() were actually tpooled + print counter[0] self.assert_(counter[0] > 10, counter[0]) - gt.wait() - + gt.kill() @skip_with_pyevent def test_raising_exceptions(self):