Watchers¶
Common methods and attributes¶
Watcher
is the base class for all watchers. Though it is not exposed
to users, its methods and attributes are described here.
-
class
Watcher
¶ See also
-
start
()¶ Starts (activates) the watcher. Only active watchers will receive events. If the watcher is already active nothing will happen.
-
stop
()¶ Stops the watcher if active, and clears the pending status (whether the watcher was active or not). It is possible that stopped watchers are pending - for example, non-repeating timers are being stopped when they become pending - but
stop()
ensures that the watcher is neither active nor pending.
-
invoke
(revents)¶ Parameters: revents (int) – See Events received for valid values. Invoke the watcher callback with the given revents.
-
clear
()¶ Return type: int If the watcher is pending, this method clears its pending status and returns its revents bitset (as if its callback was invoked). If the watcher isn’t pending it does nothing and returns
0
. Sometimes it can be useful to “poll” a watcher instead of waiting for its callback to be invoked, which can be accomplished with this method.
-
feed
(revents)¶ Parameters: revents (int) – See Events received for valid values. Feeds the given revents set into the event loop, as if the specified event had happened for the watcher.
-
callback
¶ The current watcher callback, its signature must be:
-
callback
(watcher, revents) Parameters: - watcher (a subclass of
Watcher
) – this watcher. - revents (int) – See Events received for valid values.
- watcher (a subclass of
As a rule you should not let a callback return with unhandled exceptions. The loop “does not know” how to correctly handle an exception happening in your callback (it depends largely on what you are doing), so, by default, it will just print a warning and suppress it. If you want to act on an exception, you’re better off doing it in the callback (where you are allowed to do anything needed, like logging, stopping, restarting the loop, etc.). Example:
def mycallback(watcher, revents): try: pass # do something interesting except Exception as err: # stop the watcher watcher.stop() # stop the loop watcher.loop.stop() # and finally raise err raise err
If you have a lot of callbacks, use decorators:
import logging def mydecorator(func): def wrap(watcher, revents): try: func(watcher, revents) except RuntimeError: # these are not fatal # this will also log the traceback logging.exception("stopping {0}".format(watcher)) # stop the watcher but let the loop continue on its merry way watcher.stop() except Exception as err: # all other exceptions are fatal # stop the watcher watcher.stop() # stop the loop watcher.loop.stop() # and finally raise err raise err return wrap @mydecorator def mycallback(watcher, revents): pass #do something interesting
Note
As a convenience mood.event provides a
fatal()
decorator. If a callback decorated withfatal()
raises an exception the loop is stopped and the exception raised.Contrast:
>>> from signal import SIGINT >>> from mood.event import Loop, EV_TIMER, EV_SIGNAL >>> >>> def mycallback(watcher, revents): ... if (revents & EV_TIMER): ... raise Exception("TEST") ... elif (revents & EV_SIGNAL): ... watcher.loop.stop() ... >>> >>> loop = Loop() >>> timer = loop.timer(0, 2, mycallback) >>> timer.start() >>> sig = loop.signal(SIGINT, mycallback) # will catch KeyboardInterrupt >>> sig.start() >>> loop.start() Exception ignored in: <function mycallback at 0x7f4a4b057f28> Traceback (most recent call last): File "<stdin>", line 3, in mycallback Exception: TEST Exception ignored in: <function mycallback at 0x7f4a4b057f28> Traceback (most recent call last): File "<stdin>", line 3, in mycallback Exception: TEST Exception ignored in: <function mycallback at 0x7f4a4b057f28> Traceback (most recent call last): File "<stdin>", line 3, in mycallback Exception: TEST ^CTrue >>>
and:
>>> from mood.event import Loop, fatal >>> >>> @fatal ... def mycallback(watcher, revents): ... raise Exception("TEST") ... >>> >>> loop = Loop() >>> timer = loop.timer(0, 2, mycallback) >>> timer.start() >>> loop.start() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in mycallback Exception: TEST >>>
-
-
data
¶ watcher data.
-
priority
¶ Set and query the priority of the watcher. The priority is a small integer between
EV_MINPRI
andEV_MAXPRI
. Pending watchers with higher priority will be invoked before watchers with lower priority, but priority will not keep watchers from being executed. If you need to suppress invocation when higher priority events are pending you need to look atIdle
watchers, which provide this functionality.Setting a priority outside the range of
EV_MINPRI
toEV_MAXPRI
is fine, as long as you do not mind that the priority value you query might or might not have been clamped to the valid range.The default priority used by watchers when no priority has been set is always
0
.Note
You must not change the priority of a watcher as long as it is active or pending.
See also
-
active
¶ Read only
True
if the watcher is active (i.e. it has been started and not yet been stopped),False
otherwise.Note
As long as a watcher is active you must not modify it.
-
pending
¶ Read only
True
if the watcher is pending (i.e. it has outstanding events but its callback has not yet been invoked),False
otherwise.
-
Events received¶
-
EV_PREPARE
¶ -
EV_CHECK
¶ All
Prepare
watchers are invoked just before the loop starts to gather new events, and allCheck
watchers are queued (not invoked) just after the loop has gathered them, but before it queues any callbacks for any received events. That meansPrepare
watchers are the last watchers invoked before the event loop sleeps or polls for new events, andCheck
watchers will be invoked before any other watchers of the same or lower priority within an event loop iteration. Callbacks of both watcher types can start and stop as many watchers as they want, and all of them will be taken into account (for example, aPrepare
watcher might start anIdle
watcher to keep the loop from blocking).
-
EV_CUSTOM
¶ Not ever sent (or otherwise used) by libev itself, but can be freely used by users to signal watchers (e.g. via
feed()
).
-
EV_ERROR
¶ An unspecified error has occurred, the watcher has been stopped. This might happen because the watcher could not be properly started because libev ran out of memory, a file descriptor was found to be closed or any other problem.
Warning
mood.event handle this event as a fatal error. On receiving this event the loop and the watcher will be stopped (the callback will not be invoked). In practice, users should never receive this event (still present for testing puposes).