To follow up some discussion on reddit, the subject of exceptions was
brought up. The Python 2.X/3.X compatible way to do exceptions requires:

  e = sys.exc_info()[1]

...if you need the actual exception object. As discussed on reddit, this
is slow on PyPy.

I did some checks in the py3k patch of all the cases where we actually
do this because we need the exception object. I found the following:

= Cases where slowness probably doesn't matter too much =

== Developer errors ==

 - template syntax errors and other errors

 - incorrect configuration e.g. import errors due to incorrect dotted
   to path to some component

These are generally only observed during development, not production.

== Tests ==

 - running tests - many instances at different levels of code - in
   unittest and in tests themselves.

It would be nice if test suite ran fast, but not so important.

== Runtime 'exceptional' cases ==

 - file handling errors e.g. file already exists, permission errors.
   (These are likely 'rare' cases or misconfiguration, but conceivably
   they could be common).

 - general view exception handling.

   If any exception happens in a view, (including Http404), we pass it
   to the exception handling middleware. This also applies to
   decorators created from middleware. (So, this might not be such an
   'exceptional' case).

 - crashers of various kinds, especially in management commands
   e.g. can't serialize data in dumpdata command

 - invalid HTTP requests

 - some DB operational/integrity errors (the exception object is needed
   to map between the different types of errors that should be raised)

   - most of these were already calling sys.exc_info()

= Cases where slowness probably does matter =

 - signals - errors are caught and appended to 'responses'. Signals
   can be used for all kinds of things.

 - wrapping DoesNotExist in IndexError in queryset slicing

   - we could potentially change this behaviour - do we really
     need to capture the underlying exception arguments and
     pass to IndexError?

 - Validation error handling - the validators in django.core.validators
   for URLs and email validation use an actual exception object.

 - model validation and form validation - use exceptions to pass info
   around.

 - errors that happen in templates but are silenced. (we check the
   actual exception object to see if we should silence them). Since
   they are silent, there could be any number of these going on in an
   app.

 - MultiJoin in query generation code - don't know how often this
   is thrown and caught. We could conceivably change the way this works,
   it is internal.

 - Resolver404 errors - very common, since it is part of the URL
   resolving mechanism. This is a documented API, so we can't change it.


I also found a couple of places where we can avoid creating the
exception object if `settings.DEBUG = False` - untested patch attached.

Regards,

Luke


-- 
The fashion wears out more apparel than the man.
            -- William Shakespeare

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

diff -r 9087952bd12b django/contrib/staticfiles/handlers.py
--- a/django/contrib/staticfiles/handlers.py	Fri Dec 02 16:48:14 2011 +0000
+++ b/django/contrib/staticfiles/handlers.py	Sat Dec 03 21:10:11 2011 +0000
@@ -56,8 +56,8 @@
             try:
                 return self.serve(request)
             except Http404:
-                e = sys.exc_info()[1]
                 if settings.DEBUG:
+                    e = sys.exc_info()[1]
                     from django.views import debug
                     return debug.technical_404_response(request, e)
         return super(StaticFilesHandler, self).get_response(request)
diff -r 9087952bd12b django/core/handlers/base.py
--- a/django/core/handlers/base.py	Fri Dec 02 16:48:14 2011 +0000
+++ b/django/core/handlers/base.py	Sat Dec 03 21:10:11 2011 +0000
@@ -139,7 +139,8 @@
                     response = response.render()
 
             except http.Http404:
-                e = sys.exc_info()[1]
+                if settings.DEBUG:
+                    e = sys.exc_info()[1]
                 logger.warning('Not Found: %s' % request.path,
                             extra={
                                 'status_code': 404,

Reply via email to