I sometimes get the following errors when my django app tries to get from or store something in the cache:
c = cache.get(pk)
File "/opt/python3/lib/python3.4/site-packages/django/core/cache/__init__.py", line 131, in __getattr__
return getattr(caches[DEFAULT_CACHE_ALIAS], name)
File "/opt/python3/lib/python3.4/site-packages/django/core/cache/__init__.py", line 113, in __getitem__
cache = _create_cache(alias)
File "/opt/python3/lib/python3.4/site-packages/django/core/cache/__init__.py", line 88, in _create_cache
return backend_cls(location, params)
File "/opt/python3/lib/python3.4/site-packages/django/core/cache/backends/memcached.py", line 185, in __init__
value_not_found_exception=pylibmc.NotFound)
AttributeError: 'module' object has no attribute 'NotFound'
but why? the module has the attribute, and most of the time it works, there is no file with the same name that can break this, where to look for the cause of this?
>>> import pylibmc
>>> pylibmc.NotFound
<class '_pylibmc.NotFound'>
>>>
tl;dr: try importing pylibmc at an application startup location, such as the uwsgi
or manage.py
file.
My guess is that it's a multithreading issue while importing pylibmc
in a request thread inside PyLibMCCache.__init__
as opposed to at application startup. (IMO Django does the import there because not all Django installations use pylibmc
, and thus they shouldn't force it on each app as a dependency)
While I'm not familiar enough with the internals of how import
ing works, I suspect what happens is something like the below
pylibmc
sys.modules
for pylibmc
pylibmc
->
the AttributeError
is raisedsys.modules
and now pylibmc.NotFound
is availableIn general, Python seem to discourage runtime loading of modules as opposed to startup time loading.
emphasis is mine
Note: For projects where startup time is critical, this class [
importlib.util.LazyLoader
] allows for potentially minimizing the cost of loading a module if it is never used. For projects where startup time is not essential then use of this class is heavily discouraged due to error messages created during loading being postponed and thus occurring out of context.