Question about expression evaluation

S

Scott Gould

Hi folks,

This is a head-scratcher to me. I occasionally get this error:

---
File "/var/www/myproj/account/views.py", line 54, in account
if request.account.is_instructor and request.account.contact and
request.account.contact.relationship.institution_party_number:

AttributeError: 'NoneType' object has no attribute 'relationship'
---

I'm leaving out all the supporting code deliberately. My question is
simple: if python short-circuits evaluation and
"request.account.contact" is None, how is it even getting as far as
"request.account.contact.relationship.institution_party_number"?

Thanks!
 
N

nn

Hi folks,

This is a head-scratcher to me. I occasionally get this error:

---
  File "/var/www/myproj/account/views.py", line 54, in account
    if request.account.is_instructor and request.account.contact and
request.account.contact.relationship.institution_party_number:

AttributeError: 'NoneType' object has no attribute 'relationship'
---

I'm leaving out all the supporting code deliberately. My question is
simple: if python short-circuits evaluation and
"request.account.contact" is None, how is it even getting as far as
"request.account.contact.relationship.institution_party_number"?

Thanks!

Hard to tell without details. Maybe request.account.contact is an
impure property with side effects?
 
J

Jerry Hill

---
 File "/var/www/myproj/account/views.py", line 54, in account
   if request.account.is_instructor and request.account.contact and
request.account.contact.relationship.institution_party_number:

AttributeError: 'NoneType' object has no attribute 'relationship'

Perhaps request.account is being mutated in another thread?
 
P

Peter Otten

Scott said:
Hi folks,

This is a head-scratcher to me. I occasionally get this error:

---
File "/var/www/myproj/account/views.py", line 54, in account
if request.account.is_instructor and request.account.contact and
request.account.contact.relationship.institution_party_number:

AttributeError: 'NoneType' object has no attribute 'relationship'
---

I'm leaving out all the supporting code deliberately. My question is
simple: if python short-circuits evaluation and
"request.account.contact" is None, how is it even getting as far as
"request.account.contact.relationship.institution_party_number"?

Probably a race condition: contact is set to None after

request.account.contact

is evaluated, but before

request.account.contact.relationship

is evaluated. This may happen in your case because the underlying database
was modified by a different user (I'm speculating). Here's a simulation:
.... relationship = "SUCCESS"
........ def __init__(self):
.... self._contact = Contact()
.... @property
.... def contact(self):
.... try: return self._contact
.... finally: self._contact = None
....Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'relationship'

You can avoid the problem with a different coding style:
.... print account.contact.relationship
.... except AttributeError:
.... print "failed"
....
SUCCESS

Peter
 
S

Scott Gould

Thanks for the ideas, everyone. It's probably obvious that this is in
a Django context, and while I do have WSGI configured to multi-thread
its processes, there is nothing explicitly shared -- via threading, a
multi-user situation, or otherwise -- about this data. It is entirely
local to the request so I can't figure out how the "contact" object
could change in a single line of code.

But obviously there must be something going on like what you all
suggest. I just can't figure out how. This is the entirety of the
contact-producing code within Account:

@property
def contact(self):
if not hasattr(self, '_contact'):
self._contact = get_contact_for_id(self.profile.id) if self.profile
and self.profile.id else None
return self._contact

As you can see, it's essentially read-only so once a self._contact
always a self._contact. (Unless I'm misunderstanding something
fundamental, which as an admitted amateur I could well be!)
 
P

Peter Otten

Scott said:
Thanks for the ideas, everyone. It's probably obvious that this is in
a Django context, and while I do have WSGI configured to multi-thread
its processes, there is nothing explicitly shared -- via threading, a
multi-user situation, or otherwise -- about this data. It is entirely
local to the request so I can't figure out how the "contact" object
could change in a single line of code.

But obviously there must be something going on like what you all
suggest. I just can't figure out how. This is the entirety of the
contact-producing code within Account:

@property
def contact(self):
if not hasattr(self, '_contact'):

If one thread stops this point the _contact attribute is not yet set and
another thread may trigger the if-suite, too.
self._contact =
get_contact_for_id(self.profile.id) if self.profile
 
P

Peter Otten

Scott said:
Thanks for the ideas, everyone. It's probably obvious that this is in
a Django context, and while I do have WSGI configured to multi-thread
its processes, there is nothing explicitly shared -- via threading, a
multi-user situation, or otherwise -- about this data. It is entirely
local to the request so I can't figure out how the "contact" object
could change in a single line of code.

But obviously there must be something going on like what you all
suggest. I just can't figure out how. This is the entirety of the
contact-producing code within Account:

@property
def contact(self):
if not hasattr(self, '_contact'):

If one thread stops at this point the _contact attribute is not yet set and
another thread may trigger the if-suite, too.
self._contact =
get_contact_for_id(self.profile.id) if self.profile
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top