scheduler.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. """
  2. Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
  3. This module offers extensions to the standard python 2.3+
  4. datetime module.
  5. """
  6. __author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
  7. __license__ = "PSF License"
  8. import datetime
  9. import thread
  10. import signal
  11. import time
  12. class sched:
  13. def __init__(self, rrule,
  14. tolerance=None, last=None,
  15. execute=None, args=None, kwargs=None):
  16. self._rrule = rrule
  17. if tolerance:
  18. self._tolerance = datetime.timedelta(seconds=tolerance)
  19. else:
  20. self._tolerance = None
  21. self._last = last
  22. self._execute = execute
  23. self._args = args or ()
  24. self._kwargs = kwargs or {}
  25. def last(self):
  26. return self._last
  27. def next(self, now=None):
  28. if not now:
  29. now = datetime.datetime.now()
  30. return self._rrule.after(now)
  31. def check(self, now=None, readonly=False):
  32. if not now:
  33. now = datetime.datetime.now()
  34. item = self._rrule.before(now, inc=True)
  35. if (item is None or item == self._last or
  36. (self._tolerance and item+self._tolerance < now)):
  37. return None
  38. if not readonly:
  39. self._last = item
  40. if self._execute:
  41. self._execute(*self._args, **self._kwargs)
  42. return item
  43. class schedset:
  44. def __init__(self):
  45. self._scheds = []
  46. def add(self, sched):
  47. self._scheds.append(sched)
  48. def next(self, now=None):
  49. if not now:
  50. now = datetime.datetime.now()
  51. res = None
  52. for sched in self._scheds:
  53. next = sched.next(now)
  54. if next and (not res or next < res):
  55. res = next
  56. return res
  57. def check(self, now=None, readonly=False):
  58. if not now:
  59. now = datetime.datetime.now()
  60. res = False
  61. for sched in self._scheds:
  62. if sched.check(now, readonly):
  63. res = True
  64. return res
  65. class schedthread:
  66. def __init__(self, sched, lock=None):
  67. self._sched = sched
  68. self._lock = lock
  69. self._running = False
  70. def running(self):
  71. return self._running
  72. def run(self):
  73. self._running = True
  74. thread.start_new_thread(self._loop, ())
  75. def stop(self):
  76. self._running = False
  77. def _loop(self):
  78. while self._running:
  79. if self._lock:
  80. self._lock.acquire()
  81. now = datetime.datetime.now()
  82. self._sched.check(now)
  83. if self._lock:
  84. self._lock.release()
  85. seconds = _seconds_left(self._sched.next(now))
  86. if seconds is None:
  87. self._running = False
  88. break
  89. if self._running:
  90. time.sleep(seconds)
  91. class schedalarm:
  92. def __init__(self, sched, lock=None):
  93. self._sched = sched
  94. self._lock = lock
  95. self._running = False
  96. def running(self):
  97. return self._running
  98. def run(self):
  99. self._running = True
  100. signal.signal(signal.SIGALRM, self._handler)
  101. self._handler(None, None)
  102. def stop(self):
  103. self._running = False
  104. def _handler(self, sig, frame):
  105. while self._running:
  106. if self._lock:
  107. self._lock.acquire()
  108. now = datetime.datetime.now()
  109. self._sched.check(now)
  110. if self._lock:
  111. self._lock.release()
  112. if self._running:
  113. seconds = _seconds_left(self._sched.next(now))
  114. if seconds:
  115. signal.alarm(seconds)
  116. break
  117. elif seconds is None:
  118. self._running = False
  119. break
  120. def _seconds_left(next):
  121. if not next:
  122. return None
  123. now = datetime.datetime.now()
  124. delta = next-now
  125. seconds = delta.days*86400+delta.seconds
  126. if seconds < 0:
  127. seconds = 0
  128. return seconds