[Python-bugs-list] [ python-Bugs-752221 ] print in __getattr__ causes seg fault

SourceForge.net noreply@sourceforge.net
Sun, 15 Jun 2003 06:15:47 -0700


Bugs item #752221, was opened at 2003-06-10 16:58
Message generated for change (Comment added) made by sjones
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=752221&group_id=5470

Category: Python Interpreter Core
Group: Python 2.3
Status: Open
Resolution: None
Priority: 5
Submitted By: Christopher K. Paulicka (paulicka)
Assigned to: Nobody/Anonymous (nobody)
Summary: print in __getattr__ causes seg fault

Initial Comment:
[~/site-packages/WorldPlay/] paulicka@Sliver-14:56:32
$ python
Python 2.3a2+ (#4, Mar  2 2003, 17:13:46) 
[GCC 3.1 20020420 (prerelease)] on darwin
Type "help", "copyright", "credits" or "license" for more 
information.
>>> class A:
...     def __getattr__(self,name):
...             return 3
... 
>>> a=A()
>>> a.c
3
>>> class B:
...     def __getattr__(self,name):
...             print self, name
...             return 3
... 
>>> b=B()
>>> b.c
Segmentation fault
[~/site-packages/WorldPlay/] paulicka@Sliver-14:57:14
$ 

$ uname -a
Darwin Sliver.local. 6.6 Darwin Kernel Version 6.6: Thu 
May  1 21:48:54 PDT 2003; root:xnu/xnu-344.34.obj~1/
RELEASE_PPC  Power Macintosh powerpc


----------------------------------------------------------------------

Comment By: Shannon Jones (sjones)
Date: 2003-06-15 08:15

Message:
Logged In: YES 
user_id=589306

I did some research and thinking on this problem, and here
is what I think is happening.

1. When you print self inside __getattr__, Python calls
repr(self) to figure out how to print that.
2. repr(self) attempts to call self.__repr__().
3. Since you didn't define __repr__ for this class,
__getattr__ is called to look up the name.
4. __getattr__ attempts to print self again, and you are now
in an infinite loop.

For more information, do a Google Groups search for "Obscure
__getattr__ behavior" which should bring you to the thread
at http://tinyurl.com/ecsh (hope that works, heh). It even
mentions the difference bcannon mentioned between old and
new style classes.

You could solve the problem by defining your own __repr__
(and __str__ for similar reasons). Or you can raise
AttributeError in __getattr__ if name is __repr__ or __str__
so that Python reverts back to defaults for these functions.

Here is a way to write your class so that it does what you want:

>>> class B:
...     def __getattr__(self, name):
...             if name == '__repr__' or name == '__str__':
...                     raise AttributeError
...             print self, name
...             return 3
...
>>> b = B()
>>> b.c
<__main__.B instance at 0x81c785c> c
3


I'm leaning toward the opinion that the infinite loop
behavior is not a bug in Python. Even though the result
wasn't expected, Python was doing exactly as told.

However, the Segmentation Fault you got on your system is
probably a bug. That seems related to your OS / build of
Python though. Can anyone duplicate the segfault?

Maybe Python isn't catching the infinite recursion fast
enough and your stack is overflowing (just a wild guess).
Try running some code like this and see if you get a
RuntimeError or a segfault:

def f():
    f()

Then call f() to see what error you get.



----------------------------------------------------------------------

Comment By: Brett Cannon (bcannon)
Date: 2003-06-15 02:48

Message:
Logged In: YES 
user_id=357491

I get a RuntimeError under OS X just like sjones but only with a 
classic class.  What else that is interesting is that if I just type in 
the instance name and hit enter it also has the RuntimeError.

I checked the bytecode and both are the same so there isn't 
some funky difference there.  Must be some way that classic 
classes handle self compared to new-style and how __getattr__ 
is dealt with.

----------------------------------------------------------------------

Comment By: Shannon Jones (sjones)
Date: 2003-06-13 20:57

Message:
Logged In: YES 
user_id=589306

I tried running with current CVS and got the following
results on Linux:

Python 2.3b1+ (#3, Jun 13 2003, 07:56:14)
[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-5)] on linux2
Type "help", "copyright", "credits" or "license" for more
information.
>>> class A:
...     def __getattr__(self, name):
...             return 3
...
>>> a = A()
>>> a.c
3
>>> class B:
...     def __getattr__(self, name):
...             print self, name
...             return 3
...
>>> b = B()
>>> b.c
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in __getattr__
  File "<stdin>", line 3, in __getattr__
  File "<stdin>", line 3, in __getattr__
  File "<stdin>", line 3, in __getattr__
[Repeats lots of times]
  File "<stdin>", line 3, in __getattr__
RuntimeError: maximum recursion depth exceeded
>>> class C:
...     def __init__(self):
...             self.x = 5
...     def __getattr__(self, name):
...             print self.x
...             return 3
...
>>> c = C()
>>> c.c
5
3

$ uname -a
Linux localhost 2.4.20-18.9 #1 Thu May 29 06:54:41 EDT 2003
i686 athlon i386 GNU/Linux

-------------------------------------------------
Note that I can print things from getattr, it is just
printing self that gets me in trouble.


----------------------------------------------------------------------

Comment By: Christopher K. Paulicka (paulicka)
Date: 2003-06-13 19:20

Message:
Logged In: YES 
user_id=45461

Actually, I can't use the beta, because I used the MacOS Kitchen 
Sink combination of Framework Python, Pygame and PyOpenGL.

I tried building from the CVS repository, but had problems, so 
just moved on...

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2003-06-10 22:09

Message:
Logged In: YES 
user_id=80475

Can you try this one on the beta release to see if it is still a 
problem.  I cannot reproduce the segfault on a Windows 
build.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=752221&group_id=5470