loguru icon indicating copy to clipboard operation
loguru copied to clipboard

Exception handler diagnose only works on first line

Open lobotmcj opened this issue 2 years ago • 2 comments

Love the library, by the way, thanks!

Is there a way for exception handling with diagnose=True to work on multi-line statements?

If you take the ZeroDivisionError shown in the docs, but split the exception-triggering statement across lines like so:

def inverse(x):
    try:
        1 / \
        x
    except ZeroDivisionError:
        logger.exception("Oups...")

if __name__ == "__main__":
    inverse(0)

... then the variable x is not annotated in the log output. You get something like this:

Traceback (most recent call last):                                                                                                                           
                                                                                                        
  File "<redacted>", line <redacted>, in <redacted>
    _ = 1 / \                                                                                                                                                                   
                                                                                          
ZeroDivisionError: division by zero

I realize that this example is rather arbitrary, but I am finding that statements in my stack traces often span multiple lines (e.g., to conform to code width requirements), and so much is excluded from annotation.

Edit: This is a limitation of Python logging in general (i.e., that only the first line of a statement is included in the trace), isn't it?

lobotmcj avatar Feb 16 '22 00:02 lobotmcj

Hey @lobotmcj, thanks for describing your concerns and suggesting a possible improvements to Loguru. :+1:

I agree that the diagnose parameter loses much of its utility in cases like this. I had similar thoughts to yours about the truncated lines appearing the standard traceback. I never realized it could be fixed actually. The current implementation of the diagnose option has been made by copying the classical traceback formatting, but it's not a limitation per se. Surely we can move away from the default implementation and introduce our own improvements.

It will probably require refactoring a bit the current parser to iterate lines and detect the end of the expression. It will be interesting to learn from Pytest which seems to handle this kind of case very well:

____________________________ test_1 _____________________________

    def test_1():
>       1 / \
        0
E       ZeroDivisionError: division by zero


test.py:2: ZeroDivisionError
____________________________ test_2 _____________________________

    def test_2():
>       foo(
            a,
            b,
        )
E       NameError: name 'foo' is not defined


test.py:6: NameError

A more challenging question will be how to display the values on multiple lines, as the decorative arrows ( and ) will no longer be able to access the upper lines. :thinking:

Anyway, that would be a welcome improvement, I'll try to think about it.

Delgan avatar Feb 26 '22 17:02 Delgan

@Delgan , thank you very much for looking into this! Regarding the decorative arrows, perhaps a flag to disable them and instead provide a table of variables and their values after the traceback statement? It actually might prove helpful to some people even with single-line tracebacks, as the decorative arrows can get a bit muddled up if the terminal width is small anyway.

lobotmcj avatar Feb 26 '22 17:02 lobotmcj