recursive method in __init__
Robert Brewer
fumanchu at amor.org
Wed Nov 3 18:17:59 EST 2004
paul koelle wrote:
> I thought it would be nice to have instances that can "live"
> somehow in
> the "background" and do some tasks without being told so. The
> problem in
> the code below is: calling new_host = Host(ip, mac, collector) never
> "returns" because the the self.update() method gets called
> recursively.
> Im pretty sure I have to restructure the code and call the update()
> method from outside but I ask out of curiosity and to get
> some ideas how
> to do such things elegantly.
Use threading. Try three cooperating functions:
1. run(), which does the work you want done,
2. motivate(), which starts a new thread, which starts by calling...
3. _cycle(), which calls motivate(), then run().
The example below is from Cation, a web application framework. You start
the cycle via:
>>> worker = ApplicationWorker(name, app, recurrence, **kwargs)
>>> worker.motivate()
class ApplicationWorker(object):
"""Perform work for an application on a schedule.
You must override work(), which is called at each interval.
active: a boolean flag indicating whether or not the Worker's run()
method should be executed at each interval. Notice that, even if
active is False, recurring Workers will continue to schedule new
threads--they simply won't do anything at run() time.
kwargs: a dictionary where each k, v pair represents an (optional)
kwarg to the worker. "key" should be a string, the name of the
argument. Values should be populated with defaults where
possible.
Override this at the class level when subclassing
ApplicationWorker.
"""
kwargs = {}
def __init__(self, name, application, recurrence, **kwargs):
self.name = name
self.application = application
self.log = application.logger
self.recurrence = recurrence
if self.recurrence:
# Throw away the first occurrence value,
# which is almost always .now()
self.recurrence.next()
self.kwargs = {}
self.kwargs.update(self.__class__.kwargs)
self.kwargs.update(kwargs)
self.createdate = datetime.datetime.now()
self.lastrun = None
self.active = True
def motivate(self):
"""Start a new immediate or recurring thread for work."""
if self.recurrence:
# Start a recurring, timed Thread.
nextThread = threading.Timer(self.recurrence.interval(),
self._cycle)
nextThread.start()
else:
# Start a single, non-recurring thread.
threading.Thread(None, self.run).start()
def _cycle(self):
"""Run the worker on a schedule."""
self.motivate()
self.run()
def run(self):
"""Prepare for work. Errors are logged, then ignored."""
if self.active:
try:
self.work()
self.lastrun = datetime.datetime.now()
msg = (u"Worker '%s' completed successfully." %
self.name)
self.log.info(msg)
except Exception:
self.log.exception(self.__class__.__name__)
def work(self):
raise NotImplementedError
Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org
More information about the Python-list
mailing list