Improved timeout docs.
This commit is contained in:
@@ -105,90 +105,9 @@ Though Eventlet has many modules, much of the most-used stuff is accessible simp
|
||||
|
||||
.. class:: eventlet.Timeout
|
||||
|
||||
Raises *exception* in the current greenthread after *timeout* seconds::
|
||||
|
||||
timeout = Timeout(seconds, exception)
|
||||
try:
|
||||
... # execution here is limited by timeout
|
||||
finally:
|
||||
timeout.cancel()
|
||||
|
||||
When *exception* is omitted or ``None``, the :class:`Timeout` instance
|
||||
itself is raised:
|
||||
|
||||
>>> Timeout(0.1)
|
||||
>>> eventlet.sleep(0.2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Timeout: 0.1 seconds
|
||||
|
||||
In Python 2.5 and newer, you can use the ``with`` statement for additional
|
||||
convenience::
|
||||
|
||||
with Timeout(seconds, exception) as timeout:
|
||||
pass # ... code block ...
|
||||
|
||||
This is equivalent to the try/finally block in the first example.
|
||||
This class is a way to add timeouts to anything. It raises *exception* in the current greenthread after *timeout* seconds. When *exception* is omitted or ``None``, the Timeout instance itself is raised.
|
||||
|
||||
There is an additional feature when using the ``with`` statement: if
|
||||
*exception* is ``False``, the timeout is still raised, but the with
|
||||
statement suppresses it, so the code outside the with-block won't see it::
|
||||
|
||||
data = None
|
||||
with Timeout(5, False):
|
||||
data = mysock.makefile().readline()
|
||||
if data is None:
|
||||
... # 5 seconds passed without reading a line
|
||||
else:
|
||||
... # a line was read within 5 seconds
|
||||
|
||||
As a very special case, if *seconds* is None, the timer is not scheduled,
|
||||
and is only useful if you're planning to raise it directly.
|
||||
|
||||
There are two Timeout caveats to be aware of:
|
||||
|
||||
* If the code block in the try/finally or with-block never cooperatively yields, the timeout cannot be raised. In Eventlet, this should rarely be a problem, but be aware that you cannot time out CPU-only operations with this class.
|
||||
* If the code block catches and doesn't re-raise :class:`BaseException` (for example, with ``except:``), then it will catch the Timeout exception, and might not abort as intended.
|
||||
|
||||
When catching timeouts, keep in mind that the one you catch may not be the
|
||||
one you have set; if you going to silence a timeout, always check that it's
|
||||
the same instance that you set::
|
||||
|
||||
timeout = Timeout(1)
|
||||
try:
|
||||
...
|
||||
except Timeout, t:
|
||||
if t is not timeout:
|
||||
raise # not my timeout
|
||||
|
||||
|
||||
.. function:: eventlet.with_timeout(seconds, function, *args, **kwds)
|
||||
|
||||
Wrap a call to some (yielding) function with a timeout; if the called
|
||||
function fails to return before the timeout, cancel it and return a flag
|
||||
value.
|
||||
|
||||
:param seconds: seconds before timeout occurs
|
||||
:type seconds: int or float
|
||||
:param func: the callable to execute with a timeout; it must cooperatively yield, or else the timeout will not be able to trigger
|
||||
:param \*args: positional arguments to pass to *func*
|
||||
:param \*\*kwds: keyword arguments to pass to *func*
|
||||
:param timeout_value: value to return if timeout occurs (by default raises
|
||||
:class:`Timeout`)
|
||||
|
||||
:rtype: Value returned by *func* if *func* returns before *seconds*, else
|
||||
*timeout_value* if provided, else raises :class:`Timeout`.
|
||||
|
||||
:exception Timeout: if *func* times out and no ``timeout_value`` has
|
||||
been provided.
|
||||
:exception: Any exception raised by *func*
|
||||
|
||||
Example::
|
||||
|
||||
data = with_timeout(30, urllib2.open, 'http://www.google.com/', timeout_value="")
|
||||
|
||||
Here *data* is either the result of the ``get()`` call, or the empty string
|
||||
if it took too long to return. Any exception raised by the ``get()`` call
|
||||
is passed through to the caller.
|
||||
Timeout objects are context managers, and so can be used in with statements.
|
||||
See :class:`Timeout <eventlet.timeout.Timeout>` for more details.
|
||||
|
||||
These are the basic primitives of Eventlet; there are a lot more out there in the other Eventlet modules; check out the :doc:`modules`.
|
||||
|
||||
@@ -14,4 +14,5 @@ Module Reference
|
||||
modules/pools
|
||||
modules/queue
|
||||
modules/semaphore
|
||||
modules/timeout
|
||||
modules/wsgi
|
||||
|
||||
93
doc/modules/timeout.rst
Normal file
93
doc/modules/timeout.rst
Normal file
@@ -0,0 +1,93 @@
|
||||
:mod:`timeout` -- Universal Timeouts
|
||||
========================================
|
||||
|
||||
.. class:: eventlet.timeout.Timeout
|
||||
|
||||
Raises *exception* in the current greenthread after *timeout* seconds::
|
||||
|
||||
timeout = Timeout(seconds, exception)
|
||||
try:
|
||||
... # execution here is limited by timeout
|
||||
finally:
|
||||
timeout.cancel()
|
||||
|
||||
When *exception* is omitted or ``None``, the :class:`Timeout` instance
|
||||
itself is raised:
|
||||
|
||||
>>> Timeout(0.1)
|
||||
>>> eventlet.sleep(0.2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
Timeout: 0.1 seconds
|
||||
|
||||
In Python 2.5 and newer, you can use the ``with`` statement for additional
|
||||
convenience::
|
||||
|
||||
with Timeout(seconds, exception) as timeout:
|
||||
pass # ... code block ...
|
||||
|
||||
This is equivalent to the try/finally block in the first example.
|
||||
|
||||
There is an additional feature when using the ``with`` statement: if
|
||||
*exception* is ``False``, the timeout is still raised, but the with
|
||||
statement suppresses it, so the code outside the with-block won't see it::
|
||||
|
||||
data = None
|
||||
with Timeout(5, False):
|
||||
data = mysock.makefile().readline()
|
||||
if data is None:
|
||||
... # 5 seconds passed without reading a line
|
||||
else:
|
||||
... # a line was read within 5 seconds
|
||||
|
||||
As a very special case, if *seconds* is None, the timer is not scheduled,
|
||||
and is only useful if you're planning to raise it directly.
|
||||
|
||||
There are two Timeout caveats to be aware of:
|
||||
|
||||
* If the code block in the try/finally or with-block never cooperatively yields, the timeout cannot be raised. In Eventlet, this should rarely be a problem, but be aware that you cannot time out CPU-only operations with this class.
|
||||
* If the code block catches and doesn't re-raise :class:`BaseException` (for example, with ``except:``), then it will catch the Timeout exception, and might not abort as intended.
|
||||
|
||||
When catching timeouts, keep in mind that the one you catch may not be the
|
||||
one you have set; if you going to silence a timeout, always check that it's
|
||||
the same instance that you set::
|
||||
|
||||
timeout = Timeout(1)
|
||||
try:
|
||||
...
|
||||
except Timeout, t:
|
||||
if t is not timeout:
|
||||
raise # not my timeout
|
||||
|
||||
.. automethod:: cancel
|
||||
.. autoattribute:: pending
|
||||
|
||||
|
||||
.. function:: eventlet.timeout.with_timeout(seconds, function, *args, **kwds)
|
||||
|
||||
Wrap a call to some (yielding) function with a timeout; if the called
|
||||
function fails to return before the timeout, cancel it and return a flag
|
||||
value.
|
||||
|
||||
:param seconds: seconds before timeout occurs
|
||||
:type seconds: int or float
|
||||
:param func: the callable to execute with a timeout; it must cooperatively yield, or else the timeout will not be able to trigger
|
||||
:param \*args: positional arguments to pass to *func*
|
||||
:param \*\*kwds: keyword arguments to pass to *func*
|
||||
:param timeout_value: value to return if timeout occurs (by default raises
|
||||
:class:`Timeout`)
|
||||
|
||||
:rtype: Value returned by *func* if *func* returns before *seconds*, else
|
||||
*timeout_value* if provided, else raises :class:`Timeout`.
|
||||
|
||||
:exception Timeout: if *func* times out and no ``timeout_value`` has
|
||||
been provided.
|
||||
:exception: Any exception raised by *func*
|
||||
|
||||
Example::
|
||||
|
||||
data = with_timeout(30, urllib2.open, 'http://www.google.com/', timeout_value="")
|
||||
|
||||
Here *data* is either the result of the ``get()`` call, or the empty string
|
||||
if it took too long to return. Any exception raised by the ``get()`` call
|
||||
is passed through to the caller.
|
||||
@@ -51,14 +51,18 @@ class Timeout(BaseException):
|
||||
|
||||
@property
|
||||
def pending(self):
|
||||
"""Return True if the timeout is scheduled to be raised."""
|
||||
"""True if the timeout is scheduled to be raised."""
|
||||
if self.timer is not None:
|
||||
return self.timer.pending
|
||||
else:
|
||||
return False
|
||||
|
||||
def cancel(self):
|
||||
"""If the timeout is pending, cancel it. Otherwise, do nothing."""
|
||||
"""If the timeout is pending, cancel it. If not using Timeouts in
|
||||
``with`` statements, always call cancel() in a ``finally`` after the
|
||||
block of code that is getting timed out. If not cancelled, the timeout
|
||||
will be raised later on, in some unexpected section of the
|
||||
application."""
|
||||
if self.timer is not None:
|
||||
self.timer.cancel()
|
||||
self.timer = None
|
||||
|
||||
Reference in New Issue
Block a user