1
0

stackthreading.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. # Import and use just like threading, but enjoy the benefit of seeing the
  2. # calling context prepended to any thread traceback.
  3. #
  4. # The contents of this file are subject to the Python Software Foundation
  5. # License Version 2.3 (the License). You may not copy or use this file, in
  6. # either source code or executable form, except in compliance with the License.
  7. # You may obtain a copy of the License at http://www.python.org/license.
  8. #
  9. # Software distributed under the License is distributed on an AS IS basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # by Greg Hazel
  15. import os
  16. import sys
  17. import thread
  18. import threading
  19. import traceback
  20. from threading import *
  21. def _print(stream, str='', terminator='\n'):
  22. stream.write(str+terminator)
  23. def _print_traceback(stream, base_stack, name, extra, exc_type, value, tb):
  24. stack2 = traceback.extract_tb(tb)
  25. # cut off the top
  26. stack2 = stack2[extra + 1:]
  27. base_stack.extend(stack2)
  28. l = traceback.format_list(base_stack)
  29. _print(stream, "Exception in %s:" % name)
  30. _print(stream, "Traceback (most recent call last):")
  31. for s in l:
  32. _print(stream, s, '')
  33. lines = traceback.format_exception_only(exc_type, value)
  34. for line in lines[:-1]:
  35. _print(stream, line, ' ')
  36. _print(stream, lines[-1], '')
  37. base_Thread = Thread
  38. class StackThread(Thread):
  39. def __init__(self, group=None, target=None, name=None, depth=1,
  40. args=(), kwargs={}, verbose=None):
  41. if name is None:
  42. try:
  43. raise ZeroDivisionError
  44. except ZeroDivisionError:
  45. f = sys.exc_info()[2].tb_frame.f_back
  46. stack = traceback.extract_stack(f)
  47. fn, ln, fc, cd = stack[-depth]
  48. #sys.stdout.writelines([str(s)+'\n' for s in stack])
  49. root, fn = os.path.split(fn)
  50. name = '%s:%s in %s: %s' % (fn, ln, fc, cd)
  51. base_Thread.__init__(self, group=group, target=target, name=name,
  52. args=args, kwargs=kwargs, verbose=verbose)
  53. stream = sys.stderr
  54. start = self.start
  55. def save():
  56. # ha ha ha
  57. try:
  58. raise ZeroDivisionError
  59. except ZeroDivisionError:
  60. f = sys.exc_info()[2].tb_frame.f_back
  61. self.stack = traceback.extract_stack(f)
  62. try:
  63. start()
  64. except thread.error, e:
  65. d = {}
  66. for i in threading.enumerate():
  67. i = str(i)
  68. d.setdefault(i, 0)
  69. d[i] += 1
  70. print >> stream, str(d)
  71. raise thread.error("%s, count: %d" %
  72. (str(e).strip(), len(threading.enumerate())))
  73. run = self.run
  74. def catch():
  75. try:
  76. run()
  77. except:
  78. # interpreter shutdown
  79. if not sys:
  80. return
  81. exc_type, value, tb = sys.exc_info()
  82. _print_traceback(stream, self.stack,
  83. "thread %s" % self.getName(), 1,
  84. exc_type, value, tb)
  85. self.run = catch
  86. self.start = save
  87. Thread = StackThread
  88. # this is annoying
  89. _Event = threading._Event
  90. if __name__ == '__main__':
  91. def foo():
  92. raise ValueError("boo!")
  93. t = Thread(target=foo)
  94. t.start()