Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the usage of __traceback_hide__

Tags:

python

I have seen this line of code in some functions

__traceback_hide__ = True 

What does it do? It seems like its trying to suppress the error traceback. In what situations should the traceback be hidden?

like image 615
joydeep bhattacharjee Avatar asked Sep 07 '16 04:09

joydeep bhattacharjee


4 Answers

__tracebackhide__ can be set to hide a function from the traceback when using PyTest. __traceback_hide__ appears to be used in the Python Paste package for the same purpose.

Here's what the paste.exceptions.collector documentation has to say about it:

If set and true, this indicates that the frame should be hidden from abbreviated tracebacks. This way you can hide some of the complexity of the larger framework and let the user focus on their own errors.

By setting it to 'before', all frames before this one will be thrown away. By setting it to 'after' then all frames after this will be thrown away until 'reset' is found. In each case the frame where it is set is included, unless you append '_and_this' to the value (e.g., 'before_and_this').

Note that formatters will ignore this entirely if the frame that contains the error wouldn’t normally be shown according to these rules.

And the PyTest documentation on its similar __tracebackhide__:

If you have a test helper function called from a test you can use the pytest.fail marker to fail a test with a certain message. The test support function will not show up in the traceback if you set the __tracebackhide__ option somewhere in the helper function.

So basically, they are to avoid cluttering your tracebacks with test helper functions or other functions that you know aren't part of the problem that you are trying to debug.

like image 145
David Scarlett Avatar answered Nov 08 '22 05:11

David Scarlett


Googling for "python __traceback_hide__", I learn that it's intended to let a complicated framework hide part of its inner workings by suppressing some stack frames from the exception printout, so that the user does not become confused lots of irrelevant output.

like image 23
D-Von Avatar answered Nov 08 '22 05:11

D-Von


Looks like this is mostly a convenience for web frameworks (Sentry, werkzeug, Paste, Django) to make it so framework functions aren't included in the high level exception reporting features of the frameworks.

The exact behavior likely differs by framework, for example, for Paste specifically, it's documented as:

If set and true, this indicates that the frame should be hidden from abbreviated tracebacks. This way you can hide some of the complexity of the larger framework and let the user focus on their own errors.

By setting it to 'before', all frames before this one will be thrown away. By setting it to 'after' then all frames after this will be thrown away until 'reset' is found. In each case the frame where it is set is included, unless you append '_and_this' to the value (e.g., 'before_and_this').

Note that formatters will ignore this entirely if the frame that contains the error wouldn’t normally be shown according to these rules.

It's not a standard variable, and the core Python interpreter provides no support for it.

like image 3
ShadowRanger Avatar answered Nov 08 '22 05:11

ShadowRanger


Hiding the traceback can give you more comprehensible test output.

Consider testing that a web API endpoint /running returns the JSON response {"running": true}:

import pytest
import json

def test_running(client):
    action_response = client.get('/running')
    assert parse_as_json(action_response) == {'running': True}

def parse_as_json(response):
    __tracebackhide__ = True  # <---- Point of interest
    try:
        return json.loads(response.data)
    except json.decoder.JSONDecodeError:
        pass
    pytest.fail(f'Expected JSON, but got {response.data}')

If the test fails (because the JSON is malformed), then the failure will be displayed as

__________________________ test_running _________________________

client = <FlaskClient <Flask 'webapi'>>

    def test_running(client):
        action_res = client.get('/running')
>       assert parse_as_json(action_res) == {'running': True}
E       Failed: Expected JSON, but got b'ok'

webapi_test.py:22: Failed
=============== 1 failed, 1 passed in 0.15 seconds ===============

whereas, without the __tracebackhide__ = True, the output will be

__________________________ test_running _________________________

client = <FlaskClient <Flask 'webapi'>>

    def test_running(client):
        action_res = client.get('/running')
>       assert parse_as_json(action_res) == {'running': True}

webapi_test.py:22: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

client = <FlaskClient <Flask 'webapi'>>

    def test_running(client):
        action_res = client.get('/running')
>       assert parse_as_json(action_res) == {'running': True}
E       Failed: Expected JSON, but got b'ok'

webapi_test.py:22: Failed
=============== 1 failed, 1 passed in 0.17 seconds ===============
like image 2
jpsecher Avatar answered Nov 08 '22 07:11

jpsecher