PageRenderTime 71ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/build/gevent/doc/intro.rst

https://github.com/vtemian/outclan
ReStructuredText | 215 lines | 147 code | 68 blank | 0 comment | 0 complexity | d5597fda56c5ad0dfb70687f0fb90e48 MD5 | raw file
  1. Introduction
  2. ============
  3. gevent is a Python networking library that uses greenlet_ to provide a synchronous API on top of libevent_ event loop.
  4. Features include:
  5. * Fast event loop based on libevent (epoll on Linux, kqueue on FreeBSD).
  6. * Lightweight execution units based on greenlet.
  7. * API that re-uses concepts from the Python standard library (e.g. :class:`Event`, :class:`Queue`).
  8. * Cooperative :mod:`socket` and :mod:`ssl` modules.
  9. * Ability to use standard library and 3rd party modules written for standard blocking sockets (:mod:`gevent.monkey`).
  10. * DNS queries performed through libevent-dns.
  11. * Fast WSGI server based on libevent-http.
  12. .. _greenlet: http://codespeak.net/py/0.9.2/greenlet.html
  13. .. _libevent: http://monkey.org/~provos/libevent/
  14. Installation
  15. ------------
  16. gevent runs on Python 2.4 and newer and requires
  17. * greenlet__ which can be installed with ``easy_install greenlet``.
  18. * libevent_ 1.4.x
  19. For ssl to work on Python older than 2.6, ssl_ package is required.
  20. __ http://pypi.python.org/pypi/greenlet
  21. .. _ssl: http://pypi.python.org/pypi/ssl
  22. Example
  23. -------
  24. The following example shows how to run tasks concurrently.
  25. >>> import gevent
  26. >>> from gevent import socket
  27. >>> urls = ['www.google.com', 'www.example.com', 'www.python.org']
  28. >>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
  29. >>> gevent.joinall(jobs, timeout=2)
  30. >>> [job.value for job in jobs]
  31. ['74.125.79.106', '208.77.188.166', '82.94.164.162']
  32. After the jobs have been spawned, :func:`gevent.joinall` waits for them to complete,
  33. no longer than 2 seconds though. The results are then collected by checking
  34. :attr:`gevent.Greenlet.value` property. The :func:`gevent.socket.gethostbyname` function
  35. has the same interface as the standard :func:`socket.gethostbyname` but it does not block
  36. the whole interpreter and thus lets the other greenlets to proceed with their requests as well.
  37. .. _monkey-patching:
  38. Monkey patching
  39. ---------------
  40. The example above used :mod:`gevent.socket` for socket operations. If the standard :mod:`socket`
  41. module was used it would took it 3 times longer to complete because the DNS requests would
  42. be sequential. Using the standard socket module inside greenlets makes gevent rather
  43. pointless, so what about module and packages that are built on top of :mod:`socket`?
  44. That's what monkey patching for. The functions in :mod:`gevent.monkey` carefully
  45. replace functions and classes in the standard :mod:`socket` module with their cooperative
  46. counterparts. That way even the modules that are unaware of gevent can benefit from running
  47. in multi-greenlet environment.
  48. >>> from gevent import monkey; monkey.patch_socket()
  49. >>> import urllib2 # it's usable from multiple greenlets now
  50. See `examples/concurrent_download.py`__
  51. __ http://bitbucket.org/denis/gevent/src/tip/examples/concurrent_download.py#cl-4
  52. Event loop
  53. ----------
  54. Unlike other network libraries and similar to eventlet, gevent starts
  55. the event loop implicitly in a dedicated greenlet. There's no ``reactor`` that
  56. you must ``run()`` or ``dispatch()`` function to call. When a function from
  57. gevent API wants to block, it obtains the :class:`Hub` instance - a greenlet
  58. that runs the event loop - and switches to it. If there's no :class:`Hub`
  59. instance yet, one is created on the fly.
  60. The event loop provided by libevent uses the fastest polling mechanism available
  61. on the system by default. It is possible to command libevent not to use a particular
  62. polling mechanism by setting ``EVENT_NOXXX``` environment variable where ``XXX`` is the event loop
  63. you want to disable. For example, on Linux setting ``EVENT_NOEPOLL=1`` would avoid the default
  64. ``epoll`` mechanism and use ``poll``.
  65. Libevent API is available under :mod:`gevent.core` module. Note, that the callbacks
  66. supplied to libevent API are run in the :class:`Hub` greenlet and thus cannot use synchronous
  67. gevent API. It is possible to use asynchronous API there, like :func:`spawn` and :meth:`Event.set`.
  68. Cooperative multitasking
  69. ------------------------
  70. The greenlets all run in the same OS thread and scheduled cooperatively. This means that until
  71. a particular greenlet gives up control, by calling a blocking function that will switch to the :class:`Hub`, other greenlets
  72. won't get a chance to run. It is typically not an issue for an I/O bound app, but one should be aware
  73. of this when doing something CPU intensive or calling blocking I/O functions that bypass libevent event loop.
  74. Synchronizing access to the objects shared across the greenlets is unnecessary in most cases, thus
  75. :class:`Lock` and :class:`Semaphore` classes although present aren't used as often. Other abstractions
  76. from threading and multiprocessing remain useful in the cooperative world:
  77. - :class:`Event` allows to wake up a number of greenlets that are calling :meth:`Event.wait` method.
  78. - :class:`AsyncResult` is similar to :class:`Event` but allows passing a value or an exception to the waiters.
  79. - :class:`Queue` and :class:`JoinableQueue`.
  80. Lightweight pseudothreads
  81. -------------------------
  82. .. currentmodule:: gevent.greenlet
  83. The greenlets are spawned by creating a :class:`Greenlet` instance and calling its :meth:`start <Greenlet.start>`
  84. method. (The :func:`spawn` function is a shortcut that does exactly that). The :meth:`start <Greenlet.start>`
  85. method schedules an :class:`event <gevent.core.active_event>` that will switch to the greenlet created, as soon
  86. as the current greenlet gives up control. If there is more than one active event, they will be executed
  87. one by one, in an undefined order.
  88. If there was an error during execution it won't escape greenlet's boundaries. An unhandled error results
  89. in a stacktrace being printed complemented by failed function signature and arguments:
  90. >>> gevent.spawn(lambda : 1/0)
  91. >>> gevent.sleep(1)
  92. Traceback (most recent call last):
  93. ...
  94. ZeroDivisionError: integer division or modulo by zero
  95. <Greenlet at 0x7f2ec3a4e490: <function <lambda...>> failed with ZeroDivisionError
  96. The traceback is asynchronously printed to ``sys.stderr`` when the greenlet dies.
  97. :class:`Greenlet` instances has a number of useful methods:
  98. - :meth:`join <Greenlet.join>` -- waits until the greenlet exits;
  99. - :meth:`kill <Greenlet.kill>` -- interrupts greenlet's execution;
  100. - :meth:`get <Greenlet.get>` -- returns the value returned by greenlet or re-raised the exception that killed it.
  101. It is possible to customize the string printed after the traceback by subclassing :class:`Greenlet` class
  102. and redefining its ``__str__`` method.
  103. To subclass a :class:`Greenlet`, override its :meth:`_run` method and call ``Greenlet.__init__(self)`` in ``__init__``::
  104. class MyNoopGreenlet(Greenlet):
  105. def __init__(self, seconds):
  106. Greenlet.__init__(self)
  107. self.seconds = seconds
  108. def _run(self):
  109. gevent.sleep(self.seconds)
  110. def __str__(self):
  111. return 'MyNoopGreenlet(%s)' % self.seconds
  112. Greenlets can be killed asynchronously. Killing will resume the sleeping greenlet, but instead
  113. of continuing execution, a :exc:`GreenletExit` will be raised.
  114. >>> g = MyNoopGreenlet(4)
  115. >>> g.start()
  116. >>> g.kill()
  117. >>> g.dead
  118. True
  119. The :exc:`GreenletExit` exception and its subclasses are handled differently then other exceptions.
  120. Raising :exc:`GreenletExit` is not considered an exceptional situation, so the traceback is not printed.
  121. The :exc:`GreenletExit` is returned by :meth:`get <Greenlet.get>` as if it was returned by the greenlet, not raised.
  122. The :meth:`kill <Greenlet.kill>` method can accept an exception to raise:
  123. >>> g = MyNoopGreenlet.spawn(5) # spawn() creates a Greenlet and starts it
  124. >>> g.kill(Exception("A time to kill"))
  125. Traceback (most recent call last):
  126. ...
  127. Exception: A time to kill
  128. MyNoopGreenlet(5) failed with Exception
  129. The :meth:`kill <Greenlet.kill>` can also accept a *timeout* argument specifying the number of seconds to wait for the greenlet to exit.
  130. Note, that :meth:`kill <Greenlet.kill>` cannot guarantee that the target greenlet will not ignore the exception and thus it's a good idea always to pass a timeout to :meth:`kill <Greenlet.kill>`.
  131. Timeouts
  132. --------
  133. Many functions in the gevent API are synchronous, blocking the current greenlet until the operation is done. For example,
  134. :meth:`kill <Greenlet.kill>` waits until the target greenlet is :attr:`dead` before returning [#f1]_. Many of those
  135. functions can be made asynchronous by passing ``block=False`` argument.
  136. Furthermore, many of the synchronous functions accept *timeout* argument, which specifies a limit on how long the function
  137. could block (examples: :meth:`Event.wait`, :meth:`Greenlet.join`, :meth:`Greenlet.kill`, :meth:`AsyncResult.get` and many more).
  138. The :class:`socket <gevent.socket.socket>` and :class:`SSLObject <gevent.ssl.SSLObject>` instances can also have a timeout,
  139. set by :meth:`settimeout <gevent.socket.socket.settimeout>` method.
  140. When these are not enough, the :class:`Timeout` class can be used to add timeouts to arbitrary sections of (yielding) code.
  141. Futher reading
  142. --------------
  143. To limit concurrency, use :class:`Pool` class (see `example: dns_mass_resolve.py`_).
  144. Gevent comes with TCP/SSL/HTTP/WSGI servers. See :doc:`servers`.
  145. .. _`example: dns_mass_resolve.py`: http://bitbucket.org/denis/gevent/src/tip/examples/dns_mass_resolve.py#cl-17
  146. .. rubric:: Footnotes
  147. .. [#f1] This was not the case before 0.13.0, :meth:`kill <Greenlet>` method in 0.12.2 and older was asynchronous by default.