Unexpected KeyError from lazyproperty on Python 3
See original GitHub issueLately I’ve been writing / debugging a lot of code on Python 3.6 that uses astropy.utils.lazyproperty, and whenever there’s an error thrown in a lazyproperty function, I always see this KeyError from /astropy/utils/decorators.py", line 734, in __get__ before getting the traceback I expect:
>>> from astropy.utils import lazyproperty
>>> class Ham:
... @lazyproperty
... def ham(self):
... 1 / 0
...
...
>>> Ham().ham
>>> Traceback (most recent call last):
File "/Users/deil/Library/Python/3.6/lib/python/site-packages/astropy-2.0.dev18379-py3.6-macosx-10.12-x86_64.egg/astropy/utils/decorators.py", line 734, in __get__
return obj.__dict__[self._key]
KeyError: 'ham'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/deil/Library/Python/3.6/lib/python/site-packages/astropy-2.0.dev18379-py3.6-macosx-10.12-x86_64.egg/astropy/utils/decorators.py", line 736, in __get__
val = self.fget(obj)
File "<stdin>", line 4, in ham
ZeroDivisionError: division by zero
This KeyError doesn’t occur with a normal property:
>>> class Spam:
>>> @property
... def spam(self):
... 1 / 0
...
...
>>> Spam().spam
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in spam
ZeroDivisionError: division by zero
It also doesn’t occur (or at least isn’t visible to me as a user) on Python 2.7, there I get:
>>> from astropy.utils import lazyproperty
>>> class Spam:
... @lazyproperty
... def spam(self):
... 1 / 0
...
>>> Spam().spam
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/deil/Library/Python/2.7/lib/python/site-packages/astropy-2.0.dev18379-py2.7-macosx-10.12-x86_64.egg/astropy/utils/decorators.py", line 736, in __get__
val = self.fget(obj)
File "<stdin>", line 4, in spam
ZeroDivisionError: integer division or modulo by zero
On Python 3.5 I see the same behaviour as on Python 3.6.
@embray - It looks like astropy.utils.lazyproperty is something you wrote a few years ago, and it hasn’t been touched since. Could you please comment if this is a bug or a feature?
Issue Analytics
- State:
- Created 6 years ago
- Comments:8 (8 by maintainers)
Top Results From Across the Web
Python KeyError Exceptions and How to Handle Them
The ultimate goal is to stop unexpected KeyError exceptions from being raised. The Usual Solution: .get(). If the KeyError is raised from a...
Read more >How to Fix KeyError Exceptions in Python - Rollbar
The Python KeyError is an exception that occurs when an attempt is made to access an item in a dictionary that does not...
Read more >Unexpected KeyError: in Python 2.7.10 - Stack Overflow
I am new to coding in Python and I have encountered an unexpected error with my code. Any help with this would be...
Read more >lazy property « Python recipes « ActiveState Code
This recipe adapts the existing property to provide a lazypropery decorator that does this. See the first comment below for an example usage....
Read more >How to fix Python KeyError Exceptions in simple steps?
Know about Python KeyError Exception. And learn how to handle exceptions in Python. A detailed guide to Errors and Exceptions in Python.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I wouldn’t be totally against changing this, as @cdeil suggested, to something like
The use of
obj.__dict__.get(...)avoids a repeat dictionary lookup (as opposed to usingif self._key in obj.__dict__:...). The custom sentinel singleton_NotFoundis used since this is one of those rare cases whereNonecould be a valid return value of the cached property.I don’t think it’s worth changing myself, but I can see @cdeil’s point that it’s a bit distracting and untransparent. Astropy, being primarily a library, is a case where the line between developer and user is blurred, so users should “expect” and be able to sort of understand tracebacks. That said,
lazypropertyis deep guts, and beyond easy comprehension for Python novices, so hiding its details, even in tracebacks, might be worthwhile if possible…Just to confirm that this is now fixed:
@bsipocz and @embray - Thank you!