agronholm / exceptiongroup

Backport of PEP 654 (exception groups)
Other
42 stars 20 forks source link

Override the __str__ of ExceptionGroup to include the exceptions' message #93

Closed Tsimopak closed 11 months ago

Tsimopak commented 11 months ago

Things to check first

Feature description

I was trying to use the new API of ExceptionGroup (reference https://docs.python.org/3/library/exceptions.html#exception-groups)

And it was just great, so for example if I do:

raise ExceptionGroup('Some message', [Exception('first'), Exception('second')])

The exception error looks like this:

+ Exception Group Traceback (most recent call last):
  |   File "<string>", line 1, in <module>
  | ExceptionGroup: Some message (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | Exception: first
    +---------------- 2 ----------------
    | Exception: second
    +------------------------------------

But when I try it in try except clause, it seems like the to string of Exception is to show only the ExceptionGroup's message without the messages of the exceptions as well, so for example if I do this:

try:
    raise ExceptionGroup('Some message', [Exception('first'), Exception('second')])
except Exception as e:
    print('Exception:', e)

The output would be:

Exception: Some message (2 sub-exceptions)

So my idea is to have a new class, let's say class Errors(ExceptionGroup) that would override the __str__ to include also the messages of the exception list, but I'm not sure how to do it, is there a reference to this messages exceptions? In the same way they are created in the traceback?

Use case

A usecase would be to be able to see the Exception Group exceptions' message when catching the Exceptiongroup error.

agronholm commented 11 months ago

Do you mean this? You're supposed to use either exceptiongroup.format_exception() or traceback.format_exception() (Python 3.11+) to format the exception group.

Tsimopak commented 11 months ago

Reopening the ticket issue as I thought your solution has solved my issue. I can't use format_exception since I haven't yet raised an exception, I would like to override or append something to the traceback that would be raised, so for example, I would love to do something like this:

class Errors(ExceptionGroup):
  def __traceback__(self):
    return self.__traceback__ + 'Additional traceback information...'

So In that example, self.__traceback__ would be the exception that will be built upon raising an exception.

agronholm commented 11 months ago

I'm not open to adding features that the standard library version doesn't have because I want this package to be phased out when Python 3.10 reaches end of life.

Tsimopak commented 11 months ago

@agronholm Couldn't it be done by inherit from ExceptionGroup? Can you direct me how can I do that? The most "extreme? solution would be to clone this repo and change the traceback but I want to be able to receive updates from this one, or alternately to migrate to the native ExceptionGroup

agronholm commented 11 months ago

That would only work on exception groups you raise yourself. But what about all the ones raised by the standard library and all third party libraries?

Tsimopak commented 11 months ago

They are not matter in my system, I mean, only the exceptiongroup is the one that I want to have a unique traceback. Any ideas how it can be done without cloning the repo?

agronholm commented 11 months ago

You can try to patch the BaseExceptionGroup class by replacing its __str__() method with your own version.

Tsimopak commented 11 months ago

@agronholm but __str__ won't change the traceback, is there a way to change the traceback?

agronholm commented 11 months ago

Then I don't understand what you want. This library already changes how tracebacks are formatted for exception groups.

Tsimopak commented 11 months ago

Yeah but I want to modify it, I'd like to append more info to the end of the traceback, how can it be done?

agronholm commented 11 months ago

If you want to just add more information to the exception group, you can set the __notes__ attribute (a list of strings).

Tsimopak commented 11 months ago

@agronholm Yeah this is a perfect solution! I notice that you implemented it in BaseExceptionGroup and not BaseException, is there a way to use that in a regular Exception? is there a backport for that? If not, how would you suggest me to append something only to the traceback and not to the str(exc)

agronholm commented 11 months ago

There is no way to "backport" BaseException, as it's already a part of every Python release. The only way to add notes to all exceptions is to upgrade your Python to v3.11 or later.