ionelmc / python-hunter

Hunter is a flexible code tracing toolkit.
https://python-hunter.readthedocs.io/
BSD 2-Clause "Simplified" License
794 stars 46 forks source link

Trace `traceback` #111

Closed DUOLabs333 closed 1 year ago

DUOLabs333 commented 1 year ago

When an exception is triggered and a Traceback is generated, hunter does not show the calls traceback makes (eg, it shows the opening of the files traceback does to get the lines needed, but does not show what called the open). This normally is not what someone wants, but I've run into the scenario where I need to specifically see what traceback is doing. To be fair, I'm not even sure this is possible --- I don't know whether Python exposes the module.

ionelmc commented 1 year ago

Dunno what you're doing over there but you must have some filtering on (like stdlib=False).

Eg, this looks about right:

py310-cython-nocov run-test: commands[1] | python
Python 3.10.6 (main, Aug  2 2022, 00:00:00) [GCC 12.1.1 20220507 (Red Hat 12.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import hunter
>>> with hunter.trace():
...   import traceback
...   try:
...     1/0
...   except:
...     traceback.print_exc()
...
[...]10/site-packages/hunter/__init__.py:445   return    <= trace: <hunter._tracer.Tracer object at 0x7f0ec5d37040>
                                 <stdin>:2     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
                                 <stdin>:3     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
                                 <stdin>:4     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
                                 <stdin>:4     exception  ! <module>: (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x7f0ec5da3e80>)
                                 <stdin>:5     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
                                 <stdin>:6     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
      /usr/lib64/python3.10/traceback.py:177   call      => print_exc(limit=None, file=None, chain=True)
      /usr/lib64/python3.10/traceback.py:179   line         print_exception(*sys.exc_info(), limit=limit, file=file, chain=chain)
      /usr/lib64/python3.10/traceback.py:104   call         => print_exception(exc=<class 'ZeroDivisionError'>, value=ZeroDivisionError('division by zero'), tb=<traceback object at 0x7f0ec5da3e80>, limit=None, file=None, chain=True)
      /usr/lib64/python3.10/traceback.py:116   line            value, tb = _parse_value_tb(exc, value, tb)
      /usr/lib64/python3.10/traceback.py:93    call            => _parse_value_tb(exc=<class 'ZeroDivisionError'>, value=ZeroDivisionError('division by zero'), tb=<traceback object at 0x7f0ec5da3e80>)
      /usr/lib64/python3.10/traceback.py:94    line               if (value is _sentinel) != (tb is _sentinel):
      /usr/lib64/python3.10/traceback.py:96    line               if value is tb is _sentinel:
      /usr/lib64/python3.10/traceback.py:101   line               return value, tb
      /usr/lib64/python3.10/traceback.py:101   return          <= _parse_value_tb: (ZeroDivisionError('division by zero'), <traceback object at 0x7f0ec5da3e80>)
      /usr/lib64/python3.10/traceback.py:117   line            if file is None:
      /usr/lib64/python3.10/traceback.py:118   line            file = sys.stderr
      /usr/lib64/python3.10/traceback.py:119   line            te = TracebackException(type(value), value, tb, limit=limit, compact=True)
      /usr/lib64/python3.10/traceback.py:489   call            => __init__(self=<traceback.TracebackException object at 0x7f0ec5da4130>, exc_type=<class 'ZeroDivisionError'>, exc_value=ZeroDivisionError('division by zero'), exc_traceback=<traceback object at 0x7f0ec5da3e80>, limit=None, lookup_lines=True, capture_locals=False, compact=True, _seen=None)
      /usr/lib64/python3.10/traceback.py:496   line               is_recursive_call = _seen is not None
      /usr/lib64/python3.10/traceback.py:497   line               if _seen is None:
      /usr/lib64/python3.10/traceback.py:498   line               _seen = set()
      /usr/lib64/python3.10/traceback.py:499   line               _seen.add(id(exc_value))
      /usr/lib64/python3.10/traceback.py:502   line               self.stack = StackSummary.extract(
      /usr/lib64/python3.10/traceback.py:503   line               walk_tb(exc_traceback), limit=limit, lookup_lines=lookup_lines,
      /usr/lib64/python3.10/traceback.py:504   line               capture_locals=capture_locals)
      /usr/lib64/python3.10/traceback.py:502   line               self.stack = StackSummary.extract(
      /usr/lib64/python3.10/traceback.py:338   call               => extract(klass=<class 'traceback.StackSummary'>, frame_gen=<generator object walk_tb at 0x7f0ec5d393f0>, limit=None, lookup_lines=True, capture_locals=False)
      /usr/lib64/python3.10/traceback.py:352   line                  if limit is None:
      /usr/lib64/python3.10/traceback.py:353   line                  limit = getattr(sys, 'tracebacklimit', None)
      /usr/lib64/python3.10/traceback.py:354   line                  if limit is not None and limit < 0:
      /usr/lib64/python3.10/traceback.py:356   line                  if limit is not None:
      /usr/lib64/python3.10/traceback.py:362   line                  result = klass()
      /usr/lib64/python3.10/traceback.py:363   line                  fnames = set()
      /usr/lib64/python3.10/traceback.py:364   line                  for f, lineno in frame_gen:
      /usr/lib64/python3.10/traceback.py:322   call                  => walk_tb(tb=<traceback object at 0x7f0ec5da3e80>)
      /usr/lib64/python3.10/traceback.py:328   line                     while tb is not None:
      /usr/lib64/python3.10/traceback.py:329   line                     yield tb.tb_frame, tb.tb_lineno
      /usr/lib64/python3.10/traceback.py:329   return                <= walk_tb: (<frame at 0x7f0ec60d9000, file '<stdin>', line 6, code <module>>, 4)
      /usr/lib64/python3.10/traceback.py:365   line                  co = f.f_code
      /usr/lib64/python3.10/traceback.py:366   line                  filename = co.co_filename
      /usr/lib64/python3.10/traceback.py:367   line                  name = co.co_name
      /usr/lib64/python3.10/traceback.py:369   line                  fnames.add(filename)
      /usr/lib64/python3.10/traceback.py:370   line                  linecache.lazycache(filename, f.f_globals)
      /usr/lib64/python3.10/linecache.py:147   call                  => lazycache(filename='<stdin>', module_globals={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'hunter': <module 'hunter' from '/home/ionel/open-source/python-hunter/.tox/py310-cython-nocov/lib64/python3.10/site-packages/hunter/__init__.py'>, 'traceback': <module 'traceback' from '/usr/lib64/python3.10/traceback.py'>})
      /usr/lib64/python3.10/linecache.py:160   line                     if filename in cache:
      /usr/lib64/python3.10/linecache.py:165   line                     if not filename or (filename.startswith('<') and filename.endswith('>')):
      /usr/lib64/python3.10/linecache.py:166   line                     return False
      /usr/lib64/python3.10/linecache.py:166   return                <= lazycache: False
      /usr/lib64/python3.10/traceback.py:372   line                  if capture_locals:
      /usr/lib64/python3.10/traceback.py:375   line                  f_locals = None
      /usr/lib64/python3.10/traceback.py:376   line                  result.append(FrameSummary(
      /usr/lib64/python3.10/traceback.py:377   line                  filename, lineno, name, lookup_line=False, locals=f_locals))
      /usr/lib64/python3.10/traceback.py:376   line                  result.append(FrameSummary(
      /usr/lib64/python3.10/traceback.py:259   call                  => __init__(self=<traceback.FrameSummary object at 0x7f0ec5daff60>, filename='<stdin>', lineno=4, name='<module>', lookup_line=False, locals=None, line=None)
      /usr/lib64/python3.10/traceback.py:270   line                     self.filename = filename
      /usr/lib64/python3.10/traceback.py:271   line                     self.lineno = lineno
      /usr/lib64/python3.10/traceback.py:272   line                     self.name = name
      /usr/lib64/python3.10/traceback.py:273   line                     self._line = line
      /usr/lib64/python3.10/traceback.py:274   line                     if lookup_line:
      /usr/lib64/python3.10/traceback.py:276   line                     self.locals = {k: repr(v) for k, v in locals.items()} if locals else None
      /usr/lib64/python3.10/traceback.py:276   return                <= __init__: None
      /usr/lib64/python3.10/traceback.py:364   line                  for f, lineno in frame_gen:
      /usr/lib64/python3.10/traceback.py:329   call                  => walk_tb(tb=<traceback object at 0x7f0ec5da3e80>)
      /usr/lib64/python3.10/traceback.py:330   line                     tb = tb.tb_next
      /usr/lib64/python3.10/traceback.py:328   line                     while tb is not None:
      /usr/lib64/python3.10/traceback.py:328   return                <= walk_tb: None
      /usr/lib64/python3.10/traceback.py:378   line                  for filename in fnames:
      /usr/lib64/python3.10/traceback.py:379   line                  linecache.checkcache(filename)
      /usr/lib64/python3.10/linecache.py:52    call                  => checkcache(filename='<stdin>')
      /usr/lib64/python3.10/linecache.py:56    line                     if filename is None:
      /usr/lib64/python3.10/linecache.py:58    line                     elif filename in cache:
      /usr/lib64/python3.10/linecache.py:61    line                     return
      /usr/lib64/python3.10/linecache.py:61    return                <= checkcache: None
      /usr/lib64/python3.10/traceback.py:378   line                  for filename in fnames:
      /usr/lib64/python3.10/traceback.py:381   line                  if lookup_lines:
      /usr/lib64/python3.10/traceback.py:382   line                  for f in result:
      /usr/lib64/python3.10/traceback.py:383   line                  f.line
      /usr/lib64/python3.10/traceback.py:301   call                  => line(self=<traceback.FrameSummary object at 0x7f0ec5daff60>)
      /usr/lib64/python3.10/traceback.py:303   line                     if self._line is None:
      /usr/lib64/python3.10/traceback.py:304   line                     if self.lineno is None:
      /usr/lib64/python3.10/traceback.py:306   line                     self._line = linecache.getline(self.filename, self.lineno)
      /usr/lib64/python3.10/linecache.py:26    call                     => getline(filename='<stdin>', lineno=4, module_globals=None)
      /usr/lib64/python3.10/linecache.py:30    line                        lines = getlines(filename, module_globals)
      /usr/lib64/python3.10/linecache.py:36    call                        => getlines(filename='<stdin>', module_globals=None)
      /usr/lib64/python3.10/linecache.py:40    line                           if filename in cache:
      /usr/lib64/python3.10/linecache.py:45    line                           try:
      /usr/lib64/python3.10/linecache.py:46    line                           return updatecache(filename, module_globals)
      /usr/lib64/python3.10/linecache.py:80    call                           => updatecache(filename='<stdin>', module_globals=None)
      /usr/lib64/python3.10/linecache.py:85    line                              if filename in cache:
      /usr/lib64/python3.10/linecache.py:88    line                              if not filename or (filename.startswith('<') and filename.endswith('>')):
      /usr/lib64/python3.10/linecache.py:89    line                              return []
      /usr/lib64/python3.10/linecache.py:89    return                         <= updatecache: []
      /usr/lib64/python3.10/linecache.py:46    return                      <= getlines: []
      /usr/lib64/python3.10/linecache.py:31    line                        if 1 <= lineno <= len(lines):
      /usr/lib64/python3.10/linecache.py:33    line                        return ''
      /usr/lib64/python3.10/linecache.py:33    return                   <= getline: ''
      /usr/lib64/python3.10/traceback.py:307   line                     return self._line.strip()
      /usr/lib64/python3.10/traceback.py:307   return                <= line: ''
      /usr/lib64/python3.10/traceback.py:382   line                  for f in result:
      /usr/lib64/python3.10/traceback.py:384   line                  return result
      /usr/lib64/python3.10/traceback.py:384   return             <= extract: <traceback.StackSummary object at 0x7f0ec5dafe70>
      /usr/lib64/python3.10/traceback.py:505   line               self.exc_type = exc_type
      /usr/lib64/python3.10/traceback.py:508   line               self._str = _some_str(exc_value)
      /usr/lib64/python3.10/traceback.py:169   call               => _some_str(value=ZeroDivisionError('division by zero'))
      /usr/lib64/python3.10/traceback.py:170   line                  try:
      /usr/lib64/python3.10/traceback.py:171   line                  return str(value)
      /usr/lib64/python3.10/traceback.py:171   return             <= _some_str: 'division by zero'
      /usr/lib64/python3.10/traceback.py:509   line               if exc_type and issubclass(exc_type, SyntaxError):
      /usr/lib64/python3.10/traceback.py:520   line               if lookup_lines:
      /usr/lib64/python3.10/traceback.py:521   line               self._load_lines()
      /usr/lib64/python3.10/traceback.py:574   call               => _load_lines(self=<traceback.TracebackException object at 0x7f0ec5da4130>)
      /usr/lib64/python3.10/traceback.py:576   line                  for frame in self.stack:
      /usr/lib64/python3.10/traceback.py:577   line                  frame.line
      /usr/lib64/python3.10/traceback.py:301   call                  => line(self=<traceback.FrameSummary object at 0x7f0ec5daff60>)
      /usr/lib64/python3.10/traceback.py:303   line                     if self._line is None:
      /usr/lib64/python3.10/traceback.py:307   line                     return self._line.strip()
      /usr/lib64/python3.10/traceback.py:307   return                <= line: ''
      /usr/lib64/python3.10/traceback.py:576   line                  for frame in self.stack:
      /usr/lib64/python3.10/traceback.py:576   return             <= _load_lines: None
      /usr/lib64/python3.10/traceback.py:523   line               exc_value.__suppress_context__ if exc_value is not None else False
      /usr/lib64/python3.10/traceback.py:522   line               self.__suppress_context__ = \
      /usr/lib64/python3.10/traceback.py:527   line               if not is_recursive_call:
      /usr/lib64/python3.10/traceback.py:528   line               queue = [(self, exc_value)]
      /usr/lib64/python3.10/traceback.py:529   line               while queue:
      /usr/lib64/python3.10/traceback.py:530   line               te, e = queue.pop()
      /usr/lib64/python3.10/traceback.py:531   line               if (e and e.__cause__ is not None
      /usr/lib64/python3.10/traceback.py:542   line               cause = None
      /usr/lib64/python3.10/traceback.py:544   line               if compact:
      /usr/lib64/python3.10/traceback.py:545   line               need_context = (cause is None and
      /usr/lib64/python3.10/traceback.py:546   line               e is not None and
      /usr/lib64/python3.10/traceback.py:545   line               need_context = (cause is None and
      /usr/lib64/python3.10/traceback.py:547   line               not e.__suppress_context__)
      /usr/lib64/python3.10/traceback.py:545   line               need_context = (cause is None and
      /usr/lib64/python3.10/traceback.py:550   line               if (e and e.__context__ is not None
      /usr/lib64/python3.10/traceback.py:561   line               context = None
      /usr/lib64/python3.10/traceback.py:562   line               te.__cause__ = cause
      /usr/lib64/python3.10/traceback.py:563   line               te.__context__ = context
      /usr/lib64/python3.10/traceback.py:564   line               if cause:
      /usr/lib64/python3.10/traceback.py:566   line               if context:
      /usr/lib64/python3.10/traceback.py:529   line               while queue:
      /usr/lib64/python3.10/traceback.py:529   return          <= __init__: None
      /usr/lib64/python3.10/traceback.py:120   line            for line in te.format(chain=chain):
      /usr/lib64/python3.10/traceback.py:652   call            => format(self=<traceback.TracebackException object at 0x7f0ec5da4130>, chain=True)
      /usr/lib64/python3.10/traceback.py:665   line               output = []
      /usr/lib64/python3.10/traceback.py:666   line               exc = self
      /usr/lib64/python3.10/traceback.py:667   line               while exc:
      /usr/lib64/python3.10/traceback.py:668   line               if chain:
      /usr/lib64/python3.10/traceback.py:669   line               if exc.__cause__ is not None:
      /usr/lib64/python3.10/traceback.py:672   line               elif (exc.__context__  is not None and
      /usr/lib64/python3.10/traceback.py:677   line               chained_msg = None
      /usr/lib64/python3.10/traceback.py:678   line               chained_exc = None
      /usr/lib64/python3.10/traceback.py:680   line               output.append((chained_msg, exc))
      /usr/lib64/python3.10/traceback.py:681   line               exc = chained_exc
      /usr/lib64/python3.10/traceback.py:667   line               while exc:
      /usr/lib64/python3.10/traceback.py:686   line               for msg, exc in reversed(output):
      /usr/lib64/python3.10/traceback.py:687   line               if msg is not None:
      /usr/lib64/python3.10/traceback.py:689   line               if exc.stack:
      /usr/lib64/python3.10/traceback.py:690   line               yield 'Traceback (most recent call last):\n'
      /usr/lib64/python3.10/traceback.py:690   return          <= format: 'Traceback (most recent call last):\n'
      /usr/lib64/python3.10/traceback.py:121   line            print(line, file=file, end="")
Traceback (most recent call last):
      /usr/lib64/python3.10/traceback.py:120   line            for line in te.format(chain=chain):
      /usr/lib64/python3.10/traceback.py:690   call            => format(self=<traceback.TracebackException object at 0x7f0ec5da4130>, chain=True)
      /usr/lib64/python3.10/traceback.py:691   line               yield from exc.stack.format()
      /usr/lib64/python3.10/traceback.py:405   call               => format(self=<traceback.StackSummary object at 0x7f0ec5dafe70>)
      /usr/lib64/python3.10/traceback.py:417   line                  result = []
      /usr/lib64/python3.10/traceback.py:418   line                  last_file = None
      /usr/lib64/python3.10/traceback.py:419   line                  last_line = None
      /usr/lib64/python3.10/traceback.py:420   line                  last_name = None
      /usr/lib64/python3.10/traceback.py:421   line                  count = 0
      /usr/lib64/python3.10/traceback.py:422   line                  for frame in self:
      /usr/lib64/python3.10/traceback.py:423   line                  if (last_file is None or last_file != frame.filename or
      /usr/lib64/python3.10/traceback.py:426   line                  if count > _RECURSIVE_CUTOFF:
      /usr/lib64/python3.10/traceback.py:432   line                  last_file = frame.filename
      /usr/lib64/python3.10/traceback.py:433   line                  last_line = frame.lineno
      /usr/lib64/python3.10/traceback.py:434   line                  last_name = frame.name
      /usr/lib64/python3.10/traceback.py:435   line                  count = 0
      /usr/lib64/python3.10/traceback.py:436   line                  count += 1
      /usr/lib64/python3.10/traceback.py:437   line                  if count > _RECURSIVE_CUTOFF:
      /usr/lib64/python3.10/traceback.py:439   line                  row = []
      /usr/lib64/python3.10/traceback.py:440   line                  row.append('  File "{}", line {}, in {}\n'.format(
      /usr/lib64/python3.10/traceback.py:441   line                  frame.filename, frame.lineno, frame.name))
      /usr/lib64/python3.10/traceback.py:440   line                  row.append('  File "{}", line {}, in {}\n'.format(
      /usr/lib64/python3.10/traceback.py:442   line                  if frame.line:
      /usr/lib64/python3.10/traceback.py:301   call                  => line(self=<traceback.FrameSummary object at 0x7f0ec5daff60>)
      /usr/lib64/python3.10/traceback.py:303   line                     if self._line is None:
      /usr/lib64/python3.10/traceback.py:307   line                     return self._line.strip()
      /usr/lib64/python3.10/traceback.py:307   return                <= line: ''
      /usr/lib64/python3.10/traceback.py:444   line                  if frame.locals:
      /usr/lib64/python3.10/traceback.py:447   line                  result.append(''.join(row))
      /usr/lib64/python3.10/traceback.py:422   line                  for frame in self:
      /usr/lib64/python3.10/traceback.py:448   line                  if count > _RECURSIVE_CUTOFF:
      /usr/lib64/python3.10/traceback.py:454   line                  return result
      /usr/lib64/python3.10/traceback.py:454   return             <= format: ['  File "<stdin>", line 4, in <module>\n']
      /usr/lib64/python3.10/traceback.py:691   return          <= format: '  File "<stdin>", line 4, in <module>\n'
      /usr/lib64/python3.10/traceback.py:121   line            print(line, file=file, end="")
  File "<stdin>", line 4, in <module>
      /usr/lib64/python3.10/traceback.py:120   line            for line in te.format(chain=chain):
      /usr/lib64/python3.10/traceback.py:691   call            => format(self=<traceback.TracebackException object at 0x7f0ec5da4130>, chain=True)
      /usr/lib64/python3.10/traceback.py:692   line               yield from exc.format_exception_only()
      /usr/lib64/python3.10/traceback.py:587   call               => format_exception_only(self=<traceback.TracebackException object at 0x7f0ec5da4130>)
      /usr/lib64/python3.10/traceback.py:600   line                  if self.exc_type is None:
      /usr/lib64/python3.10/traceback.py:604   line                  stype = self.exc_type.__qualname__
      /usr/lib64/python3.10/traceback.py:605   line                  smod = self.exc_type.__module__
      /usr/lib64/python3.10/traceback.py:606   line                  if smod not in ("__main__", "builtins"):
      /usr/lib64/python3.10/traceback.py:611   line                  if not issubclass(self.exc_type, SyntaxError):
      /usr/lib64/python3.10/traceback.py:612   line                  yield _format_final_exc_line(stype, self._str)
      /usr/lib64/python3.10/traceback.py:161   call                  => _format_final_exc_line(etype='ZeroDivisionError', value='division by zero')
      /usr/lib64/python3.10/traceback.py:162   line                     valuestr = _some_str(value)
      /usr/lib64/python3.10/traceback.py:169   call                     => _some_str(value='division by zero')
      /usr/lib64/python3.10/traceback.py:170   line                        try:
      /usr/lib64/python3.10/traceback.py:171   line                        return str(value)
      /usr/lib64/python3.10/traceback.py:171   return                   <= _some_str: 'division by zero'
      /usr/lib64/python3.10/traceback.py:163   line                     if value is None or not valuestr:
      /usr/lib64/python3.10/traceback.py:166   line                     line = "%s: %s\n" % (etype, valuestr)
      /usr/lib64/python3.10/traceback.py:167   line                     return line
      /usr/lib64/python3.10/traceback.py:167   return                <= _format_final_exc_line: 'ZeroDivisionError: division by zero\n'
      /usr/lib64/python3.10/traceback.py:612   return             <= format_exception_only: 'ZeroDivisionError: division by zero\n'
      /usr/lib64/python3.10/traceback.py:692   return          <= format: 'ZeroDivisionError: division by zero\n'
      /usr/lib64/python3.10/traceback.py:121   line            print(line, file=file, end="")
ZeroDivisionError: division by zero
      /usr/lib64/python3.10/traceback.py:120   line            for line in te.format(chain=chain):
      /usr/lib64/python3.10/traceback.py:692   call            => format(self=<traceback.TracebackException object at 0x7f0ec5da4130>, chain=True)
      /usr/lib64/python3.10/traceback.py:612   call               => format_exception_only(self=<traceback.TracebackException object at 0x7f0ec5da4130>)
      /usr/lib64/python3.10/traceback.py:612   return             <= format_exception_only: None
      /usr/lib64/python3.10/traceback.py:686   line               for msg, exc in reversed(output):
      /usr/lib64/python3.10/traceback.py:686   return          <= format: None
      /usr/lib64/python3.10/traceback.py:120   return       <= print_exception: None
      /usr/lib64/python3.10/traceback.py:179   return    <= print_exc: None
                                 <stdin>:1     line      ??? NO SOURCE: Source code string for '<stdin>' is empty.
>>>
DUOLabs333 commented 1 year ago

I meant something along the lines of

l

A traceback will be raised, but hunter doesn't show what operations traceback makes. I'm not using traceback explicitly.

ionelmc commented 1 year ago

Please provide a reproducer. I don't understand what you're trying to trace.

DUOLabs333 commented 1 year ago

Ok, the python script

l

will fail because l is undefined. Therefore, a traceback will be made. However, hunter will not show the actions of the interpreter's traceback (maybe because it's written in C)?

However, your example gave me an idea:

try:
except:
traceback.print_exc()

fixes the problem that I was using hunter to hunt down. The problem occurs only with the interpreter's traceback, which looks like it's different from the traceback module.

ionelmc commented 1 year ago

Yes indeed, the default excepthook is implemented in C, thus not traceable. You want to do something like this early in your script:

import sys, traceback
sys.excepthook = traceback.print_exception

Then everything will trace as expected.

DUOLabs333 commented 1 year ago

Hey, it worked! Thanks.

DUOLabs333 commented 1 year ago

How did you know that is what is needed?

ionelmc commented 1 year ago

I became acutely aware of excepthook when Ubuntu started abusing it for error reporting :-)