#3012: Traceback when using locmem cache backend
--------------------------+-------------------------------------------------
   Reporter:  Alex Dedul  |                Owner:  jacob       
     Status:  reopened    |            Component:  Cache system
    Version:              |           Resolution:              
   Keywords:              |                Stage:  Accepted    
  Has_patch:  1           |           Needs_docs:  0           
Needs_tests:  0           |   Needs_better_patch:  1           
--------------------------+-------------------------------------------------
Comment (by Sundance):

 Hi Jacob,
 
 I am afraid weakrefs are not going to help you here. Weakrefs are a means
 to get a reference to an object without increasing that object's reference
 count. It's useful when you need to build an intricate data structure with
 some precise memory management; but accessing an object through a weakref
 ''does'' modify its state, so this is not going to be a workable solution
 to this here issue.
 
 In truth, this looks like a Python bug; we should probably report it as
 such, if it hasn't been done yet. There is not much we can do about it on
 Django's side, however, except perhaps work around it one way or another.
 
 One such way is to cache pickled strings instead of the objects
 themselves, as in the other caching backends. (The caching API ''does''
 explicitly mandates that the cached objects be picklable). Here's a patch
 against trunk that changes the locmem backend's behavior accordingly:
 
 {{{
 Index: trunk/django/core/cache/backends/locmem.py
 ===================================================================
 --- trunk/django/core/cache/backends/locmem.py  (revision 4664)
 +++ trunk/django/core/cache/backends/locmem.py  (working copy)
 @@ -2,7 +2,11 @@
 
  from django.core.cache.backends.simple import CacheClass as
 SimpleCacheClass
  from django.utils.synch import RWLock
 -import copy, time
 +import time
 +try:
 +    import cPickle as pickle
 +except ImportError:
 +    import pickle
 
  class CacheClass(SimpleCacheClass):
      def __init__(self, host, params):
 @@ -20,7 +24,10 @@
              elif exp < now:
                  should_delete = True
              else:
 -                return copy.deepcopy(self._cache[key])
 +                try:
 +                    return pickle.loads(self._cache[key])
 +                except (pickle.PickleError, TypeError):
 +                    return default
          finally:
              self._lock.reader_leaves()
          if should_delete:
 @@ -35,7 +42,10 @@
      def set(self, key, value, timeout=None):
          self._lock.writer_enters()
          try:
 -            SimpleCacheClass.set(self, key, value, timeout)
 +            try:
 +                SimpleCacheClass.set(self, key, pickle.dumps(value),
 timeout)
 +            except (pickle.PickleError, TypeError):
 +                pass
          finally:
              self._lock.writer_leaves()
 
 }}}
 
 This actually works surprisingly well. I've not noticed any performance
 impact.
 
 Hope this helps!
 
 With kind regards,
 
 -- S.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/3012#comment:12>
Django Code <http://code.djangoproject.com/>
The web framework for perfectionists with deadlines
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to