gevent.hub
- The Event Loop and the Hub#
The hub is a special greenlet created automatically to run the event loop.
The current hub can be retrieved with get_hub
.
- get_hub()[source]#
Return the hub for the current thread.
If a hub does not exist in the current thread, a new one is created of the type returned by
get_hub_class()
.Deprecated since version 1.3b1: The
*args
and**kwargs
arguments are deprecated. They were only used when the hub was created, and so were non-deterministic—to be sure they were used, all callers had to pass them, or they were order-dependent. Useset_hub
instead.Changed in version 1.5a3: The args and kwargs arguments are now completely ignored.
Changed in version 23.7.0: The long-deprecated
args
andkwargs
parameters are no longer accepted.
- class Hub(loop=None, default=None)[source]#
Bases:
WaitOperationsGreenlet
A greenlet that runs the event loop.
It is created automatically by
get_hub()
.Switching
Every time this greenlet (i.e., the event loop) is switched to, if the current greenlet has a
switch_out
method, it will be called. This allows a greenlet to take some cleanup actions before yielding control. This method should not call any gevent blocking functions.- wait(watcher)#
Wait until the watcher (which must not be started) is ready.
The current greenlet will be unscheduled during this time.
- cancel_wait(watcher, error, close_watcher=False)#
Cancel an in-progress call to
wait()
by throwing the given error in the waiting greenlet.Changed in version 1.3a1: Added the close_watcher parameter. If true, the watcher will be closed after the exception is thrown. The watcher should then be discarded. Closing the watcher is important to release native resources.
Changed in version 1.3a2: Allow the watcher to be
None
. No action is taken in that case.
- loop#
- the event loop object (`ILoop`) associated with this hub and thus
- this native thread.
- destroy(destroy_loop=None)[source]#
Destroy this hub and clean up its resources.
If you manually create hubs, or you use a hub or the gevent blocking API from multiple native threads, you should call this method before disposing of the hub object reference. Ideally, this should be called from the same thread running the hub, but it can be called from other threads after that thread has exited.
Once this is done, it is impossible to continue running the hub. Attempts to use the blocking gevent API with pre-existing objects from this native thread and bound to this hub will fail.
Changed in version 20.5.1: Attempt to ensure that Python stack frames and greenlets referenced by this hub are cleaned up. This guarantees that switching to the hub again is not safe after this. (It was never safe, but it’s even less safe.)
Note that this only works if the hub is destroyed in the same thread it is running in. If the hub is destroyed by a different thread after a
fork()
, for example, expect some garbage to leak.
- exception_stream()[source]#
The stream to which exceptions will be written. Defaults to
sys.stderr
unless assigned. Assigning a false (None) value disables printing exceptions.New in version 1.2a1.
- handle_error(context, type, value, tb)[source]#
Called by the event loop when an error occurs. The default action is to print the exception to the
exception stream
.The arguments
type
,value
, andtb
are the standard tuple as returned bysys.exc_info()
. (Note that when this is called, it may not be safe to callsys.exc_info()
.)Errors that are
not errors
are not printed.Errors that are
system errors
are passed tohandle_system_error()
after being printed.Applications can set a property on the hub instance with this same signature to override the error handling provided by this class. This is an advanced usage and requires great care. This function must not raise any exceptions.
- Parameters:
context – If this is
None
, indicates a system error that should generally result in exiting the loop and being thrown to the parent greenlet.
- handle_system_error(type, value, tb=None)[source]#
Called from
handle_error
when the exception type is determined to be asystem error
.System errors cause the exception to be raised in the main greenlet (the parent of this hub).
Changed in version 20.5.1: Allow passing the traceback to associate with the exception if it is rethrown into the main greenlet.
- join(timeout=None)[source]#
Wait for the event loop to finish. Exits only when there are no more spawned greenlets, started servers, active timeouts or watchers.
Caution
This doesn’t clean up all resources associated with the hub. For that, see
destroy()
.
- run()[source]#
Entry-point to running the loop. This method is called automatically when the hub greenlet is scheduled; do not call it directly.
- Raises:
gevent.exceptions.LoopExit – If the loop finishes running. This means that there are no other scheduled greenlets, and no active watchers or servers. In some situations, this indicates a programming error.
- NOT_ERROR = (<class 'greenlet.GreenletExit'>, <class 'SystemExit'>)#
Instances of these classes are not considered to be errors and do not get logged/printed when raised by the event loop.
- SYSTEM_ERROR = (<class 'KeyboardInterrupt'>, <class 'SystemExit'>, <class 'SystemError'>)#
If instances of these classes are raised into the event loop, they will be propagated out to the main greenlet (where they will usually be caught by Python itself)
- property main_hub#
Is this the hub for the main thread?
New in version 1.3b1.
- name = ''#
A string giving the name of this hub. Useful for associating hubs with particular threads. Printed as part of the default repr.
New in version 1.3b1.
- property resolver#
The DNS resolver that the socket functions will use.
See also
- property threadpool#
The threadpool associated with this hub.
Usually this is a
gevent.threadpool.ThreadPool
, but youcan customize that
.Use this object to schedule blocking (non-cooperative) operations in a different thread to prevent them from halting the event loop.
- threadpool_size = 10#
The size we use for our threadpool. Either use a subclass for this, or change it immediately after creating the hub.
The Event Loop#
The current event loop can be obtained with get_hub().loop
.
All implementations of the loop provide a common minimum interface.
- interface ILoop[source]#
The common interface expected for all event loops.
Caution
This is an internal, low-level interface. It may change between minor versions of gevent.
Watchers
The methods that create event loop watchers are
io
,timer
,signal
,idle
,prepare
,check
,fork
,async_
,child
,stat
. These all return various types ofIWatcher
.All of those methods have one or two common arguments. ref is a boolean saying whether the event loop is allowed to exit even if this watcher is still started. priority is event loop specific.
- default#
Boolean indicating whether this is the default loop
- Implementation:
zope.schema.Bool
- Read Only:
True
- Required:
True
- Default Value:
None
- Allowed Type:
- approx_timer_resolution#
Floating point number of seconds giving (approximately) the minimum resolution of a timer (and hence the minimun value the sleep can sleep for). On libuv, this is fixed by the library, but on libev it is just a guess and the actual value is system dependent.
- Implementation:
zope.schema.Float
- Read Only:
True
- Required:
True
- Default Value:
None
- Allowed Type:
- run(nowait=False, once=False)#
Run the event loop.
This is usually called automatically by the hub greenlet, but in special cases (when the hub is not running) you can use this to control how the event loop runs (for example, to integrate it with another event loop).
- now()#
now() -> float
Return the loop’s notion of the current time.
This may not necessarily be related to
time.time()
(it may have a different starting point), but it must be expressed in fractional seconds (the same units used bytime.time()
).
- update_now()#
Update the loop’s notion of the current time.
New in version 1.3: In the past, this available as
update
. This is still available as an alias but will be removed in the future.
- destroy()#
Clean up resources used by this loop.
If you create loops (especially loops that are not the default) you should call this method when you are done with the loop.
Caution
As an implementation note, the libev C loop implementation has a finalizer (
__del__
) that destroys the object, but the libuv and libev CFFI implementations do not. The C implementation may change.
- io(fd, events, ref=True, priority=None)#
Create and return a new IO watcher for the given fd.
events is a bitmask specifying which events to watch for. 1 means read, and 2 means write.
- closing_fd(fd)#
Inform the loop that the file descriptor fd is about to be closed.
The loop may choose to schedule events to be delivered to any active IO watchers for the fd. libev does this so that the active watchers can be closed.
- Returns:
A boolean value that’s true if active IO watchers were queued to run. Closing the FD should be deferred until the next run of the eventloop with a callback.
- timer(after, repeat=0.0, ref=True, priority=None)#
Create and return a timer watcher that will fire after after seconds.
If repeat is given, the timer will continue to fire every repeat seconds.
- signal(signum, ref=True, priority=None)#
Create and return a signal watcher for the signal signum, one of the constants defined in
signal
.This is platform and event loop specific.
- idle(ref=True, priority=None)#
Create and return a watcher that fires when the event loop is idle.
- prepare(ref=True, priority=None)#
Create and return a watcher that fires before the event loop polls for IO.
Caution
This method is not supported by libuv.
- check(ref=True, priority=None)#
Create and return a watcher that fires after the event loop polls for IO.
- fork(ref=True, priority=None)#
Create a watcher that fires when the process forks.
Availability: Unix.
- async_(ref=True, priority=None)#
Create a watcher that fires when triggered, possibly from another thread.
Changed in version 1.3: This was previously just named
async
; for compatibility with Python 3.7 whereasync
is a keyword it was renamed. On older versions of Python the old name is still around, but it will be removed in the future.
- child(pid, trace=0, ref=True)#
Create a watcher that fires for events on the child with process ID pid.
This is platform specific and not available on Windows.
Availability: Unix.
- stat(path, interval=0.0, ref=True, priority=None)#
Create a watcher that monitors the filesystem item at path.
If the operating system doesn’t support event notifications from the filesystem, poll for changes every interval seconds.
- run_callback(func, *args)#
Run the func passing it args at the next opportune moment.
The next opportune moment may be the next iteration of the event loop, the current iteration, or some other time in the future.
Returns a
ICallback
object. See that documentation for important caveats.See also
asyncio.loop.call_soon()
Theasyncio
equivalent.
- run_callback_threadsafe(func, *args)#
Like
run_callback()
, but for use from outside the thread that is running this loop.This not only schedules the func to run, it also causes the loop to notice that the func has been scheduled (e.g., it causes the loop to wake up).
New in version 21.1.0.
See also
asyncio.loop.call_soon_threadsafe()
Theasyncio
equivalent.
- interface IWatcher[source]#
An event loop watcher.
These objects call their callback function when the event loop detects the event has happened.
Important
You must call
close()
when you are done with this object to avoid leaking native resources.- start(callback, *args, **kwargs)#
Have the event loop begin watching for this event.
When the event is detected, callback will be called with args.
Caution
Not all watchers accept
**kwargs
, and some watchers define special meanings for certain keyword args.
- stop()#
Have the event loop stop watching this event.
In the future you may call
start()
to begin watching again.
- close()#
Dispose of any native resources associated with the watcher.
If we were active, stop.
Attempting to operate on this object after calling close is undefined. You should dispose of any references you have to it after calling this method.
- interface ICallback[source]#
Represents a function that will be run some time in the future.
Callback functions run in the hub, and as such they cannot use gevent’s blocking API; any exception they raise cannot be caught.
- pending#
Has this callback run yet?
- Implementation:
zope.schema.Bool
- Read Only:
True
- Required:
True
- Default Value:
None
- Allowed Type:
Utilities#
- class Waiter(hub=None)[source]#
Bases:
object
A low level communication utility for greenlets.
Waiter is a wrapper around greenlet’s
switch()
andthrow()
calls that makes them somewhat safer:switching will occur only if the waiting greenlet is executing
get()
method currently;any error raised in the greenlet is handled inside
switch()
andthrow()
if
switch()
/throw()
is called before the receiver callsget()
, thenWaiter
will store the value/exception. The followingget()
will return the value/raise the exception.
The
switch()
andthrow()
methods must only be called from theHub
greenlet. Theget()
method must be called from a greenlet other thanHub
.>>> from gevent.hub import Waiter >>> from gevent import get_hub >>> result = Waiter() >>> timer = get_hub().loop.timer(0.1) >>> timer.start(result.switch, 'hello from Waiter') >>> result.get() # blocks for 0.1 seconds 'hello from Waiter' >>> timer.close()
If switch is called before the greenlet gets a chance to call
get()
thenWaiter
stores the value.>>> from gevent.time import sleep >>> result = Waiter() >>> timer = get_hub().loop.timer(0.1) >>> timer.start(result.switch, 'hi from Waiter') >>> sleep(0.2) >>> result.get() # returns immediately without blocking 'hi from Waiter' >>> timer.close()
Warning
This is a limited and dangerous way to communicate between greenlets. It can easily leave a greenlet unscheduled forever if used incorrectly. Consider using safer classes such as
gevent.event.Event
,gevent.event.AsyncResult
, orgevent.queue.Queue
.- get()[source]#
If a value/an exception is stored, return/raise it. Otherwise until switch() or throw() is called.
- switch(value)[source]#
Switch to the greenlet if one’s available. Otherwise store the value.
Changed in version 1.3b1: The value is no longer optional.
Exceptions#
- class LoopExit[source]#
Bases:
Exception
Exception thrown when the hub finishes running (
gevent.hub.Hub.run
would return).In a normal application, this is never thrown or caught explicitly. The internal implementation of functions like
gevent.hub.Hub.join()
andgevent.joinall()
may catch it, but user code generally should not.Caution
Errors in application programming can also lead to this exception being raised. Some examples include (but are not limited too):
greenlets deadlocking on a lock;
using a socket or other gevent object with native thread affinity from a different thread
- property hub#
The (optional) hub that raised the error.
New in version 20.12.0.
The following exceptions are not expected to be thrown and are not meant to be caught; if they are raised to user code it is generally a serious programming error or a bug in gevent, greenlet, or its event loop implementation. They are presented here for documentation purposes only.
- class ConcurrentObjectUseError[source]#
Bases:
AssertionError
Raised when an object is used (waited on) by two greenlets independently, meaning the object was entered into a blocking state by one greenlet and then another while still blocking in the first one.
This is usually a programming error.
See also
- class BlockingSwitchOutError[source]#
Bases:
AssertionError
Raised when a gevent synchronous function is called from a low-level event loop callback.
This is usually a programming error.
- class InvalidSwitchError[source]#
Bases:
AssertionError
Raised when the event loop returns control to a greenlet in an unexpected way.
This is usually a bug in gevent, greenlet, or the event loop.