Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

py/modsys.c: Add sys._exc_traceback. #11244

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

DavidEGrayson
Copy link
Contributor

@DavidEGrayson DavidEGrayson commented Apr 12, 2023

This new function makes it easier to provide custom formatting of exception stack traces, for example to make them fit on a tiny 16x8-character display. (Without this, I think you'd have to call sys.print_exception, somehow get the output as a string, and then scrape information from that string.)

I'm thinking of this as an experimental function that exposes internal details of MicroPython and therefore might change in the future. That's why it has the underscore in the name.

Here is an example of its output:

['test.py', 4, 'foo', 'test.py', 7, '<module>']

The regular output from sys.print_exception for the same exception is:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
  File "test.py", line 4, in foo
ZeroDivisionError: divide by zero

Both outputs were generated by the following script:

import sys

def foo():
  1/0

try:
  foo()
except Exception as e:
  sys.print_exception(e)
  print(sys._exc_traceback(e))

Is this the right approach for getting info about exception stack traces? I'd be happy to change the name, change the output format, add tests, or add documentation.

@github-actions
Copy link

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:  +336 +0.042% standard[incl +32(data)]
      stm32:  +148 +0.038% PYBV10
        rp2:  +176 +0.054% PICO

@codecov-commenter
Copy link

codecov-commenter commented Apr 12, 2023

Codecov Report

Merging #11244 (d872e6e) into master (bde222c) will decrease coverage by 0.06%.
The diff coverage is 0.00%.

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@            Coverage Diff             @@
##           master   #11244      +/-   ##
==========================================
- Coverage   98.50%   98.44%   -0.06%     
==========================================
  Files         155      155              
  Lines       20549    20561      +12     
==========================================
  Hits        20241    20241              
- Misses        308      320      +12     
Impacted Files Coverage Δ
py/modsys.c 73.91% <0.00%> (-26.09%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@dpgeorge
Copy link
Member

First thing to ask is how would one do this in CPython?

Then we need to consider if it's worth the cost (code size) and whether it should be guarded by a config macro. I would say yes it should be, but then at what level would it be enabled, eg MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES.

@DavidEGrayson
Copy link
Contributor Author

DavidEGrayson commented Apr 14, 2023

You can get this info in CPython is like this:

import traceback

def foo():
    1/0

try:
    foo()
except Exception as e:
    tb = e.__traceback__
    while tb is not None:
        print("====")
        print("  filename: " + str(tb.tb_frame.f_code.co_filename))
        print("  line: " + str(tb.tb_lineno))
        print("  name: " + str(tb.tb_frame.f_code.co_name))
        tb = tb.tb_next

This involves at least three different classes: traceback, frame, and code. The latter two contain quite a few things:

dir(tb): ['tb_frame', 'tb_lasti', 'tb_lineno', 'tb_next']
dir(frame): ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'f_back', 'f_builtins', 'f_code', 'f_globals', 'f_lasti', 'f_lineno', 'f_locals', 'f_trace', 'f_trace_lines', 'f_trace_opcodes']
dir(code): ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lines', 'co_linetable', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_posonlyargcount', 'co_stacksize', 'co_varnames', 'replace']

The Python standard library also comes with a traceback module that introduces more classes. MicroPython implements a minimal traceback module.

CPython does not have sys.print_exception like MicroPython does.

@DavidEGrayson
Copy link
Contributor Author

I changed it so that this function is only enabled by default if MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES is 1. (I'm glad to see this provides it for the RP2 boards.) I also added documentation.

@DavidEGrayson DavidEGrayson force-pushed the pr_traceback branch 2 times, most recently from 14c94e2 to 4b5c6c3 Compare April 21, 2023 01:13
This makes it easier to provide custom formatting of exception
stack traces, e.g. to make them fit on a tiny display.

This is an experimental function that exposes internal details
of MicroPython and it might change in the future.

Signed-off-by: David (Pololu) <dev-david@pololu.com>
@projectgus
Copy link
Contributor

This is an automated heads-up that we've just merged a Pull Request
that removes the STATIC macro from MicroPython's C API.

See #13763

A search suggests this PR might apply the STATIC macro to some C code. If it
does, then next time you rebase the PR (or merge from master) then you should
please replace all the STATIC keywords with static.

Although this is an automated message, feel free to @-reply to me directly if
you have any questions about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants