frame.f_locals['__class__'] -- When does it (not) exist and why?

kevinarpe at gmail.com kevinarpe at gmail.com
Sun Nov 16 07:28:13 CET 2014


Apologies for previous code example.  Yes, the 'def class' should read: 'class'.

Writing a sample to better demonstrate the issue made me realize that super() is doing something special.  It is injecting the magic '__class__' local.

I should rephrase my question: How do I get the declaring class from from a traceback object?  Currently, I cannot see how to do it.  Magic local '__class__' is not always available.  And locals 'cls' and 'self' may come from subclasses.

Code sample:

import inspect
import sys


class X:
    def __init__(self):
        # Magic local '__class__' is missing
        raise ValueError()

class Y(X):
    def __init__(self):
        super().__init__()

class X2:
    def __init__(self):
        # Calling super() here will 'inject' magic local '__class__'
        super().__init__()
        raise ValueError()

class Y2(X2):
    def __init__(self):
        super().__init__()

def main():
    _main(lambda: Y())
    _main(lambda: Y2())

def _main(func):
    try:
        func()
    except:
        (exc_type, exc_value, traceback) = sys.exc_info()
        tb = traceback
        while tb:
            frame = tb.tb_frame
            # See: code.co_freevars.  Sometimes magic '__class__' appears.
            code = frame.f_code
            lineno = frame.f_lineno
            func_name = code.co_name
            file_path = code.co_filename
            module = inspect.getmodule(frame, file_path)
            module_name = module.__name__
            print("File: {}, Line: {}, Func: {}, Module: {}".format(file_path, lineno, func_name, module_name))
            for name in ('__class__', 'self', 'cls'):
                if name in frame.f_locals:
                    print("    {}: '{}'".format(name, frame.f_locals[name]))
            tb = tb.tb_next
        print()

if __name__ == '__main__':
    main()



More information about the Python-list mailing list