Django model.DoesNotExist exception somehow replaced with an AttributeError - python

I'm experiencing an odd exception on a Django 1.5 site:
"TypeError: 'exceptions.AttributeError' object is not callable"
Essentially it looks like the model.DoesNotExist exception has been replaced with an AttributeError.
The error is intermittent, but once it happens it seems to 'stick' until I restart the process, which makes me think it might be a case of the model class getting incorrectly set in the course of a particular request, and then persisting.
Bottom of traceback:
File "/opt/mysite/django/apps/profiles/models.py", line 353, in profile_from_cache
profile = self.get(user=user_id)
File "/opt/mysite/.virtualenvs/django/lib/python2.7/site-packages/django/db/models/manager.py", line 143, in get
return self.get_query_set().get(*args, **kwargs)
File "/opt/mysite/.virtualenvs/django/lib/python2.7/site-packages/django/db/models/query.py", line 404, in get
self.model._meta.object_name)
TypeError: 'exceptions.AttributeError' object is not callable
Line of code from django/db/models/query.py:
if not num:
raise self.model.DoesNotExist(
"%s matching query does not exist." %
self.model._meta.object_name)
So it looks as if it's trying to pass a message to the DoesNotExist exception on the model, but it's somehow been replaced by an AttributeError instead.
The issue only seems to happen from http requests - if I do the same action from the command line I just get a DoesNotExist exception (which is what should be happening).
I can't find any obvious reason this should be happening. Any ideas?
(PS this seems to be the same issue. The user's answer to it, I think, is wrong: https://groups.google.com/forum/#!topic/django-users/k9JMyXlUt3Q)
Possibly relevant code
Here is an outline of the model manager:
class CacheManager(models.Manager):
def profile_from_cache(self, user_id=None):
profile = cache.get("profile_%s" % user_id)
if profile is None:
try:
profile = self.get(user=user_id)
except Profile.DoesNotExist:
return None
cache.set("profile_%s" % user_id, profile, settings.CACHE_TIMEOUT)
return profile
...
class Profile(models.Model):
...
caches = CacheManager()
Here's the line of code that seems to be causing the error. In this case it's in some middleware, but there are a few different places, all causing the same thing.
Profile.caches.profile_from_cache(user_id=request.user.pk)

It was because of incorrect syntax elsewhere in the project, that caught multiple exceptions like this:
try:
do_something()
except AttributeError, Profile.DoesNotExist:
pass
When it should have been this:
try:
do_something()
except (AttributeError, Profile.DoesNotExist):
pass
What was happening was that when this happened, AttributeError got assigned to Profile.DoesNotExist in memory, so when it was raised later, it was the wrong exception.
Thanks to this post for helping.

Related

how can i use try and except while getting model objects?

I have to use a try and except block with the following code, as I am trying to get a model class object but in case if database is empty so for that I need to use try and except.
if(txStatus=='SUCCESS'):
order=Order.objects.get(id=id) #NEED TRY ACCEPT BLOCK FOR THIS
URL = payment_collection_webhook_url
request_data ={}
json_data = json.dumps(request_data)
requests.post(url = URL, data = json_data)
return Response(status=status.HTTP_200_OK)
try..except..else..finally block works like this:
try:
order=Order.objects.get(id=id)
except ObjectDoesNotExist(or MultipleObjectsReturned in case it returns more
than 1 queryset or instance):
...Handle the exception, Write any code you want
else:
...This gets called if there is no exception or error, means it will
execute right after try statement if there's no error, so if you want
something more to happen only if the code doesn't throw an error, you can
write it here
finally:
...This gets executed no matter what in any case, means if there's
something you want to execute regardless of whether it throws an
exception or not, you write it here.
It is as simple as this:
try:
order = Order.objects.get(id=order_id)
except Order.DoesNotExist:
# Exception thrown when the .get() function does not find any item.
pass # Handle the exception here.
You can find more information about DoesNotExist exception here.
#Hagyn is correct, but in Django there is another way to do that:
Something like this:
orders = Order.objects.filter(id=order_id)
if orders.exists():
order = orders.last()
else:
# do rest of the things

Python web scraping, skip url if error

I'm trying to scrape one site (about 7000 links, all in a list), and because of my method, it is taking a LONG time and I guess that I'm ok with that (since that implies staying undetected). But if I do get any kind of error in trying to retrieve a page, can I just skip it?? Right now, if there's an error, the code breaks and gives me a bunch of error messages. Here's my code:
Collection is a list of lists and the resultant file. Basically, I'm trying to run a loop with get_url_data() (which I have a previous question to thank for) with all my url's in urllist. I have something called HTTPError but that doesn't seem to handle all the errors, hence this post. In a related side-quest, it would also be nice to get a list of the url's that couldn't process, but that's not my main concern (but it would be cool if someone could show me how).
Collection=[]
def get_url_data(url):
try:
r = requests.get(url, timeout=10)
r.raise_for_status()
except HTTPError:
return None
site = bs4.BeautifulSoup(r.text)
groups=site.select('div.filters')
word=url.split("/")[-1]
B=[]
for x in groups:
B.append(word)
T=[a.get_text() for a in x.select('div.blahblah [class=txt]')]
A1=[a.get_text() for a in site.select('div.blah [class=txt]')]
if len(T)==1 and len(A1)>0 and T[0]=='verb' and A1[0]!='as in':
B.append(T)
B.append([a.get_text() for a in x.select('div.blahblah [class=ttl]')])
B.append([a.get_text() for a in x.select('div.blah [class=text]')])
Collection.append(B)
B=[]
for url in urllist:
get_url_data(url)
I think the main error code was this, which triggered other ones Because there were a bunch of errors starting with During handling of the above exception, another exception occurred.
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 319, in _make_request
httplib_response = conn.getresponse(buffering=True)
TypeError: getresponse() got an unexpected keyword argument 'buffering'
You can make your try-catch block look like this,
try:
r = requests.get(url, timeout=10)
r.raise_for_status()
except Exception:
return
The Exception class will handle all the errors and exception.
If you want to get the exception message you can print this in your except block. You have then instantiate exception first before raising it.
except Exception as e:
print(e.message)
return

What could be the reason for lxml.etree.relaxng to return DocumentInvalid without logging an error?

I have code as follows:
try:
schema = lxml.etree.RelaxNG(file=schema_file)
schema.assertValid(etree)
except lxml.etree.DocumentInvalid as exception:
print(schema.error_log)
print(exception.error_log)
raise exception
It consistently raises a DocumentInvalid error:
DocumentInvalid: Document does not comply with schema
yet prints no errors in either the schema error log or the global error log.
This only happens for some files, others validate correctly, or give a reason for failing to validate. (It's a very long schema, so I won't quote it here.)
I don't even know where to start looking. What could the cause possibly be?
That is how you can get an error message
try:
schema = lxml.etree.RelaxNG(file=schema_file)
schema.assertValid(etree)
except lxml.etree.DocumentInvalid as exception:
print(exception.error_log.filter_from_errors()[0])
raise exception

AssertRaises fails even though exception is raised

I am running into the following rather strange problem:
I am developing a django app and in my models class I am defining an exception that should be raised when a validation fails:
class MissingValueException(Exception):
"""Raise when a required attribute is missing."""
def __init__(self, message):
super(MissingValueException, self).__init__()
self.message = message
def __str__(self):
return repr(self.message)
This code is called from a publication class in a validation method:
def validate_required_fields(self):
# Here is the validation code.
if all_fields_present:
return True
else:
raise MissingValueException(errors)
In my unit test I create a case where the exception should be raised:
def test_raise_exception_incomplete_publication(self):
publication = Publication(publication_type="book")
self.assertRaises(MissingValueException, publication.validate_required_fields)
This produces the following output:
======================================================================
ERROR: test_raise_exception_incomplete_publication (core_knowledge_platform.core_web_service.tests.logic_tests.BusinessLogicTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/media/data/Dokumente/Code/master_project/core_knowledge_platform/../core_knowledge_platform/core_web_service/tests/logic_tests.py", line 45, in test_raise_exception_incomplete_publication
self.assertRaises(MissingValueException, method, )
File "/usr/lib/python2.7/unittest/case.py", line 465, in assertRaises
callableObj(*args, **kwargs)
File "/media/data/Dokumente/Code/master_project/core_knowledge_platform/../core_knowledge_platform/core_web_service/models.py", line 150, in validate_required_fields
raise MissingValueException(errors)
MissingValueException: 'Publication of type book is missing field publisherPublication of type book is missing field titlePublication of type book is missing field year'
So it looks like the exception is raised (which is the case - I even checked it in an interactive IPython session), but it seems that assertRaises is not catching it.
Anyone has any idea why this might happen?
Thanks
This could happen if your tests and your product code are importing your exception class through two different paths, so asserRaises doesn't realize that the exception you got was the one you were looking for.
Look at your imports, make sure that they are the same in both places. Having the same directories available in two different ways in your PYTHONPATH can make this happen. Symbolic links in those entries can also confuse things.

How to raise Suds.WebFault from python code?

I am trying to raise a Suds.WebFault from python code. The __init__ method\constructor takes three arguments __init__(self, fault, document). The fault has fault.faultcode and fault.detail members\attributes\properties. I could not find out what class fault belongs to no matte what I tried. How do I raise Suds.WebFault type exception from python code?
Thanks in advance.
Not sure what exactly you are asking but you can throw a web fault using:
import suds
try:
client.service.Method(parameter)
except suds.WebFault, e:
print e
WebFault is defined in suds.__init__.py as:
class WebFault(Exception):
def __init__(self, fault, document):
if hasattr(fault, 'faultstring'):
Exception.__init__(self, u"Server raised fault: '%s'" %
fault.faultstring)
self.fault = fault
self.document = document
Therefore to raise a WebFault with a meaningful message you will need to pass an object as the first param with the message. Document can simply be None unless required.
import suds
class Fault(object):
faultstring = 'my error message'
raise suds.WebFault(Fault(), document=None)
WebFault is only meant to be actually raised when a <Fault> element is returned by the web server. So it's probably a bad idea to raise that yourself.
If you still would like to, I would start looking at the code where the framework raises it: https://github.com/unomena/suds/blob/4e90361e13fb3d74915eafc1f3a481400c798e0e/suds/bindings/binding.py#L182 - and work backwards from there.

Categories