[PYTHON] À propos de «RuntimeWarning: la version Django de l'instance de modèle Pickled n'est pas spécifiée»

Cet article est l'article du 6ème jour du Calendrier de l'Avent Python Partie 2 2015.

Si vous mettez à niveau Django de la 1.7 vers la 1.8 ou plus

RuntimeWarning: Pickled model instance's Django version is not specified.
  obj = pickle.loads(value)

Vous pouvez voir un avertissement comme celui-ci.

Je me demandais si cela se produirait toujours lors de la désérialisation d'une instance de modèle avec Pickle, mais parfois cet avertissement n'était pas affiché et les conditions étaient inconnues, j'ai donc recherché la cause.

Cause de l'avertissement

En termes simples, cela se produit lorsque vous désérialisez des données de modèle sérialisées dans une application exécutant Django 1.7 ou antérieur dans une application exécutant Django 1.8 ou supérieur.

Le code à l'origine de l'avertissement est ici.

Vous pouvez facilement le reproduire en créant un environnement avec 1.7, 1.8 / 1.9 installé avec virtualenv etc. et en changeant de version avec la même application.

Définissez le cache avec le virtualenv de Django 1.7 comme suit.

$ python manage.py shell
>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from myapp.models import MyModel
>>> obj = MyModel.objects.get(pk=1)
>>> caches['default'].set('my-model-instance', pickle.dumps(obj))

Désérialisez l'instance de modèle du cache avec virtualenv de Django 1.8 comme suit.

$ python manage.py shell
>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from myapp.models import MyModel
>>> pickle.loads(caches['default'].get('my-model-instance'))
<string>:1: RuntimeWarning: Pickled model instance's Django version is not specified.

solution de contournement

Ce qui suit peut être considéré comme un remède.

ignorer

Je ne suis pas sûr, mais pour autant que je lise les commentaires dans le code source de Django, cela ne semble pas avoir d'effet sans la propriété chargée différée dans defer.

De plus, les caches volatiles comme Memcache seront remplacés par de nouveaux caches au fil du temps, le problème devrait donc disparaître.

Vider le cache lors de la mise à niveau de Django

Je ne le recommande pas.

$ python manage.py shell
>>> from django.core.cache import caches
>>> caches['default'].clear()

Vous pouvez également définir KEY_PREFIX dans settings.py sur CACHES. Changer com / en / 1.9 / ref / settings / # key-prefix) ou incrémenter VERSION A presque le même effet que la suppression du cache.

Changer uniquement la clé de cache des données marinées

C'est la méthode que j'essaie d'attraper.

En mettant le numéro de version de Django dans la clé du cache, même si la version est mise à jour dans le futur, un autre cache sera automatiquement utilisé pour chaque version.

>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from django.utils.version import get_version
>>> from myapp.models import MyModel
>>> obj = MyModel.objects.get(pk=1)
>>> caches['default'].set('{}:my-model-instance'.format(get_version()), pickle.dumps(obj))

Le seul problème est lors de la mise en cache de l'instance de modèle pickled, donc si vous corrigez la partie pertinente comme ci-dessus, vous ne devriez pas avoir de problèmes même si vous mettez à niveau vers la version 1.9 ou supérieure. ..

Recommended Posts

À propos de «RuntimeWarning: la version Django de l'instance de modèle Pickled n'est pas spécifiée»
[Erreur Django] L'objet 'RenameAttributes' n'est pas itérable
À propos du fait que softmax n'est pas nécessaire à la fin du modèle de Torchvision.