Issue752221
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2003-06-10 21:58 by paulicka, last changed 2022-04-10 16:09 by admin. This issue is now closed.
Messages (7) | |||
---|---|---|---|
msg16338 - (view) | Author: Christopher K. Paulicka (paulicka) | Date: 2003-06-10 21:58 | |
[~/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 |
|||
msg16339 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2003-06-11 03:09 | |
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. |
|||
msg16340 - (view) | Author: Christopher K. Paulicka (paulicka) | Date: 2003-06-14 00:20 | |
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... |
|||
msg16341 - (view) | Author: Shannon Jones (sjones) | Date: 2003-06-14 01:57 | |
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. |
|||
msg16342 - (view) | Author: Brett Cannon (brett.cannon) * ![]() |
Date: 2003-06-15 07:48 | |
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. |
|||
msg16343 - (view) | Author: Shannon Jones (sjones) | Date: 2003-06-15 13:15 | |
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. |
|||
msg16344 - (view) | Author: Brett Cannon (brett.cannon) * ![]() |
Date: 2003-06-15 21:13 | |
Logged In: YES user_id=357491 Sounds reasonable to me. Building off of this, I realized why this doesn't loop for new-style classes; __getattr__ is assigned lowest priority in the attribute lookup order. This means object's __str__ kicks in before __getattr__ is ever called when trying to resolve for __str__ for the print statement. And since I am running OS X and cannot reproduce this with Python 2.3b1 I am going to close this bug fix. Thanks for the help, sjones. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-10 16:09:08 | admin | set | github: 38627 |
2003-06-10 21:58:52 | paulicka | create |