Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #80853 > unrolled thread
| Started by | kevinarpe@gmail.com |
|---|---|
| First post | 2014-11-15 21:25 -0800 |
| Last post | 2014-11-15 22:28 -0800 |
| Articles | 3 — 2 participants |
Back to article view | Back to comp.lang.python
frame.f_locals['__class__'] -- When does it (not) exist and why? kevinarpe@gmail.com - 2014-11-15 21:25 -0800
Re: frame.f_locals['__class__'] -- When does it (not) exist and why? Chris Angelico <rosuav@gmail.com> - 2014-11-16 16:40 +1100
Re: frame.f_locals['__class__'] -- When does it (not) exist and why? kevinarpe@gmail.com - 2014-11-15 22:28 -0800
| From | kevinarpe@gmail.com |
|---|---|
| Date | 2014-11-15 21:25 -0800 |
| Subject | frame.f_locals['__class__'] -- When does it (not) exist and why? |
| Message-ID | <c1287648-21e0-457b-ac41-010642a41e9c@googlegroups.com> |
Hello,
I am CPython 3.4+ user on Linux.
I am writing a little library for myself to improve the traceback module -- print_exc() and friends. I want to include the module name, class name (if possible), and function name.
Some background: traceback.print_exc() iterates through traceback objects returned by sys.exc_info()[2]. traceback.tb_frame holds each stack frame. (I call this 'frame' below.)
My improved library nearly works, but I noticed a strange corner case around frame.f_locals['__class__'].
When super().__init__() is called, a 'magic' local appears in frame.f_locals called '__class__'. Helpfully, it has the correct class for the context, which will differ from type(self). (I discovered this magic local by poking around in the debugger. I am unable to find any official documentation on it.)
Here is the quirk: In the last class in a chain of super.__init__() calls, this magic local disappears. So I have no idea the correct class for the context. I am stuck with frame.f_locals['self'].
How can I recover the correct class for the context in the last __init__() method?
I noticed if I chance the last class to inherit from object, the magic local '__class__' appears again.
A little code to demonstrate:
# do not subclass object here
def class X:
def __init__(self):
# frame.f_locals['__class__'] does not exist
pass
def class Y(X):
def __init__(self):
# frame.f_locals['__class__'] == Y
super().__init__()
def class Z(Y):
def __init__(self):
super().__init__()
# subclass object here
def class X2(object):
def __init__(self):
# frame.f_locals['__class__'] == X2
pass
def class Y2(X2):
def __init__(self):
# frame.f_locals['__class__'] == Y2
super().__init__()
def class Z2(Y2):
def __init__(self):
super().__init__()
Thanks,
Arpe
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-11-16 16:40 +1100 |
| Message-ID | <mailman.15870.1416116415.18130.python-list@python.org> |
| In reply to | #80853 |
On Sun, Nov 16, 2014 at 4:25 PM, <kevinarpe@gmail.com> wrote:
> When super().__init__() is called, a 'magic' local appears in frame.f_locals called '__class__'. Helpfully, it has the correct class for the context, which will differ from type(self). (I discovered this magic local by poking around in the debugger. I am unable to find any official documentation on it.)
>
Interesting. Are you sure you can't get the class name via the
function, rather than depending on this magic local? That seems
fragile.
Your example code isn't currently runnable ("def class"); can you
provide a self-contained program that actually attempts to display
something? It'd be helpful for those of us who aren't familiar with
internal and esoteric details of tracebacks and __init__ :)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | kevinarpe@gmail.com |
|---|---|
| Date | 2014-11-15 22:28 -0800 |
| Message-ID | <bb97d169-0555-411b-97cf-7b756d8d645e@googlegroups.com> |
| In reply to | #80856 |
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()
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web