threading_timer_decorator.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. from __future__ import print_function
  2. import sys
  3. import threading
  4. from time import sleep
  5. try:
  6. import thread
  7. except ImportError:
  8. import _thread as thread
  9. try: # use code that works the same in Python 2 and 3
  10. range, _print = xrange, print
  11. def print(*args, **kwargs):
  12. flush = kwargs.pop('flush', False)
  13. _print(*args, **kwargs)
  14. if flush:
  15. kwargs.get('file', sys.stdout).flush()
  16. except NameError:
  17. pass
  18. def cdquit(fn_name):
  19. # print to stderr, unbuffered in Python 2.
  20. print('{0} took too long'.format(fn_name), file=sys.stderr)
  21. sys.stderr.flush() # Python 3 stderr is likely buffered.
  22. thread.interrupt_main() # raises KeyboardInterrupt
  23. def exit_after(s):
  24. '''
  25. use as decorator to exit process if
  26. function takes longer than s seconds
  27. '''
  28. def outer(fn):
  29. def inner(*args, **kwargs):
  30. timer = threading.Timer(s, cdquit, args=[fn.__name__])
  31. timer.start()
  32. try:
  33. result = fn(*args, **kwargs)
  34. finally:
  35. timer.cancel()
  36. return result
  37. return inner
  38. return outer
  39. def call_method_with_timeout(method, timeout, *args, **kwargs):
  40. return exit_after(timeout)(method)(*args, **kwargs)
  41. @exit_after(1)
  42. def a():
  43. print('a')
  44. @exit_after(2)
  45. def b():
  46. print('b')
  47. sleep(1)
  48. @exit_after(3)
  49. def c():
  50. print('c')
  51. sleep(2)
  52. @exit_after(4)
  53. def d():
  54. print('d started')
  55. for i in range(10):
  56. sleep(1)
  57. print(i)
  58. @exit_after(5)
  59. def countdown(n):
  60. print('countdown started', flush=True)
  61. for i in range(n, -1, -1):
  62. print(i, end=', ', flush=True)
  63. sleep(1)
  64. print('countdown finished')
  65. def main():
  66. a()
  67. b()
  68. c()
  69. try:
  70. d()
  71. except KeyboardInterrupt as error:
  72. print('d should not have finished, printing error as expected:')
  73. print(error)
  74. countdown(3)
  75. countdown(10)
  76. print('This should not print!!!')
  77. if __name__ == '__main__':
  78. main()