debug.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. # -*- coding: utf-8 -
  2. #
  3. # This file is part of gunicorn released under the MIT license.
  4. # See the NOTICE for more information.
  5. """The debug module contains utilities and functions for better
  6. debugging Gunicorn."""
  7. import sys
  8. import linecache
  9. import re
  10. import inspect
  11. __all__ = ['spew', 'unspew']
  12. _token_spliter = re.compile(r'\W+')
  13. class Spew(object):
  14. def __init__(self, trace_names=None, show_values=True):
  15. self.trace_names = trace_names
  16. self.show_values = show_values
  17. def __call__(self, frame, event, arg):
  18. if event == 'line':
  19. lineno = frame.f_lineno
  20. if '__file__' in frame.f_globals:
  21. filename = frame.f_globals['__file__']
  22. if (filename.endswith('.pyc') or
  23. filename.endswith('.pyo')):
  24. filename = filename[:-1]
  25. name = frame.f_globals['__name__']
  26. line = linecache.getline(filename, lineno)
  27. else:
  28. name = '[unknown]'
  29. try:
  30. src = inspect.getsourcelines(frame)
  31. line = src[lineno]
  32. except IOError:
  33. line = 'Unknown code named [%s]. VM instruction #%d' % (
  34. frame.f_code.co_name, frame.f_lasti)
  35. if self.trace_names is None or name in self.trace_names:
  36. print('%s:%s: %s' % (name, lineno, line.rstrip()))
  37. if not self.show_values:
  38. return self
  39. details = []
  40. tokens = _token_spliter.split(line)
  41. for tok in tokens:
  42. if tok in frame.f_globals:
  43. details.append('%s=%r' % (tok, frame.f_globals[tok]))
  44. if tok in frame.f_locals:
  45. details.append('%s=%r' % (tok, frame.f_locals[tok]))
  46. if details:
  47. print("\t%s" % ' '.join(details))
  48. return self
  49. def spew(trace_names=None, show_values=False):
  50. """Install a trace hook which writes incredibly detailed logs
  51. about what code is being executed to stdout.
  52. """
  53. sys.settrace(Spew(trace_names, show_values))
  54. def unspew():
  55. """Remove the trace hook installed by spew.
  56. """
  57. sys.settrace(None)