Cooperative Timeouts Using gevent.Timeout
#
Cooperative timeouts can be implemented with the
gevent.Timeout
class, and the helper function
gevent.with_timeout()
.
- class Timeout(seconds=None, exception=None, ref=True, priority=-1)[source]#
Bases:
BaseException
Raise exception in the current greenlet after seconds have elapsed:
timeout = Timeout(seconds, exception) timeout.start() try: ... # exception will be raised here, after *seconds* passed since start() call finally: timeout.close()
Warning
You must always call
close
on aTimeout
object you have created, whether or not the code that the timeout was protecting finishes executing before the timeout elapses (whether or not theTimeout
exception is raised) Thistry/finally
construct or awith
statement is a good pattern. (If the timeout object will be started again, usecancel
instead ofclose
; this is rare. You must stillclose
it when you are done.)When exception is omitted or
None
, theTimeout
instance itself is raised:>>> import gevent >>> gevent.Timeout(0.1).start() >>> gevent.sleep(0.2) Traceback (most recent call last): ... Timeout: 0.1 seconds
If the seconds argument is not given or is
None
(e.g.,Timeout()
), then the timeout will never expire and never raise exception. This is convenient for creating functions which take an optional timeout parameter of their own. (Note that this is not the same thing as a seconds value of0
.)def function(args, timeout=None): "A function with an optional timeout." timer = Timeout(timeout) with timer: ...
Caution
A seconds value less than
0.0
(e.g.,-1
) is poorly defined. In the future, support for negative values is likely to do the same thing as a value ofNone
or0
A seconds value of
0
requests that the event loop spin and poll for I/O; it will immediately expire as soon as control returns to the event loop.Use As A Context Manager
To simplify starting and canceling timeouts, the
with
statement can be used:with gevent.Timeout(seconds, exception) as timeout: pass # ... code block ...
This is equivalent to the try/finally block above with one additional feature: if exception is the literal
False
, the timeout is still raised, but the context manager suppresses it, so the code outside the with-block won’t see it.This is handy for adding a timeout to the functions that don’t support a timeout parameter themselves:
data = None with gevent.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
Caution
If
readline()
above catches and doesn’t re-raiseBaseException
(for example, with a bareexcept:
), then your timeout will fail to function and control won’t be returned to you when you expect.Catching Timeouts
When catching timeouts, keep in mind that the one you catch may not be the one you have set (a calling function may have set its own timeout); if you going to silence a timeout, always check that it’s the instance you need:
timeout = Timeout(1) timeout.start() try: ... except Timeout as t: if t is not timeout: raise # not my timeout finally: timeout.close()
Changed in version 1.1b2: If seconds is not given or is
None
, no longer allocate a native timer object that will never be started.Changed in version 1.1: Add warning about negative seconds values.
Changed in version 1.3a1: Timeout objects now have a
close()
method that must be called when the timeout will no longer be used to properly clean up native resources. Thewith
statement does this automatically.- __exit__(typ, value, tb)[source]#
Stop the timer.
Changed in version 1.3a1: The underlying native timer is also stopped. This object cannot be used again.
- cancel()[source]#
If the timeout is pending, cancel it. Otherwise, do nothing.
The timeout object can be
started
again. If you will not start the timeout again, you should useclose()
instead.
- close()[source]#
Close the timeout and free resources. The timer cannot be started again after this method has been used.
- classmethod start_new(timeout=None, exception=None, ref=True, _one_shot=False)[source]#
Create a started
Timeout
.This is a shortcut, the exact action depends on timeout’s type:
If timeout is a
Timeout
, then call itsstart()
method if it’s not already begun.Otherwise, create a new
Timeout
instance, passing (timeout, exception) as arguments, then call itsstart()
method.
Returns the
Timeout
instance.
- property pending#
True if the timeout is scheduled to be raised.