Created
March 16, 2010 23:44
-
-
Save mrts/334682 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Thread-safe Django cache backend for pylibmc. | |
Tested on Python 2.6, should work on 2.5 as well. | |
Use it by setting CACHE_BACKEND in settings.py, e.g.: | |
CACHE_BACKEND = 'projdir.utils.pylibmcd://127.0.0.1:11211/' | |
And here's how to properly install pylibmcd in Ubuntu for mod_wsgi: | |
--- | |
VENV_PATH=/some/path/venv | |
virtualenv --no-site-packages $VENV_PATH | |
wget -O - http://launchpad.net/libmemcached/1.0/0.41/+download/libmemcached-0.41.tar.gz | tar zxf - | |
cd libmemcached-0.41 | |
BASE_LIBPATH=$VENV_PATH/lib/share | |
./configure --prefix $BASE_LIBPATH | |
make install | |
export CPATH=$BASE_LIBPATH/include/ | |
export LIBRARY_PATH=$BASE_LIBPATH/lib/ | |
export LD_RUN_PATH=$LIBRARY_PATH | |
pip --environment=$VENV_PATH install pylibmc | |
--- | |
The trick lies in setting LD_RUN_PATH so that mod_wsgi can find the shared libs. | |
""" | |
from __future__ import with_statement | |
from django.core.cache.backends.base import BaseCache | |
from django.utils.encoding import smart_unicode, smart_str | |
import pylibmc | |
class CacheClass(BaseCache): | |
def __init__(self, server, params): | |
super(CacheClass, self).__init__(params) | |
mc = pylibmc.Client(server.split(';')) | |
mc.behaviors = {"tcp_nodelay": True} | |
self._pool = pylibmc.ThreadMappedPool(mc) | |
def _call(self, method, *params): | |
with self._pool.reserve() as mc: | |
return getattr(mc, method)(*params) | |
def add(self, key, value, timeout=None): | |
if isinstance(value, unicode): | |
value = value.encode('utf-8') | |
return self._call('add', smart_str(key), value, | |
self.default_timeout if timeout is None else timeout) | |
def get(self, key, default=None): | |
val = self._call('get', smart_str(key)) | |
if val is None: | |
return default | |
else: | |
if isinstance(val, basestring): | |
return smart_unicode(val) | |
else: | |
return val | |
def set(self, key, value, timeout=None): | |
if isinstance(value, unicode): | |
value = value.encode('utf-8') | |
self._call('set', smart_str(key), value, | |
self.default_timeout if timeout is None else timeout) | |
def delete(self, key): | |
self._call('delete', smart_str(key)) | |
def get_many(self, keys): | |
return self._call('get_multi', map(smart_str, keys)) | |
def set_many(self, mapping, timeout=None): | |
return self._call('set_multi', | |
dict((smart_str(key), val) for key, val in mapping.iteritems()), | |
self.default_timeout if timeout is None else timeout) | |
def close(self, **kwargs): | |
self._pool.master.disconnect_all() | |
def incr(self, key, delta=1): | |
return self._call('incr', smart_str(key), delta) | |
def decr(self, key, delta=1): | |
return self._call('decr', smart_str(key), delta) |
Thanks :).
Perhaps this should go into some package or something, or should it simply stay as a Gist until the Django ticket is fixed?
I'd rather say let it stay as a Gist till then. After all, it's properly documented, no :)?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Neat.