2013-08-15 2 views
3

merci à l'avance :)Django et Céleri: incapable de tâche de conserves au vinaigre

J'ai ce async appel tâche Céleri:

update_solr.delay(id, context) 

où id est un entier et le contexte est un dict Python.

Ma définition de tâche ressemble à:

@task 
def update_solr(id, context): 
    clip = Clip.objects.get(pk=id) 
    clip_serializer = SOLRClipSerializer(clip, context=context) 
    response = requests.post(url, data=clip_serializer.data) 

clip_serializer.data est un dict et url est une chaîne représentant une URL.

Quand je tente d'appeler update_solr.delay(), je reçois cette erreur:

PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed 

Aucune des args à la tâche sont des méthodes d'instance, donc je suis confus.

Lorsque le code de tâche est exécuté de manière synchrone, aucune erreur.

Mise à jour: Correction de commentaires sur le passage de pk au lieu de l'objet.

+1

Pour éviter les conditions de course et réduire la taille de la charge utile, il est préférable de transmettre le modèle PK plutôt qu'une instance de modèle. – AndrewS

+0

Tout à fait raison, mais cela ne résout pas le problème. – hamsterdam

+0

Quelque chose * dans les objets est * une méthode d'instance (c'est-à-dire que vous mettez Object.foomethod dans un dictionnaire, ou quelque chose de similaire), dans un endroit où pickle ne peut pas le décaper. –

Répondre

3

Le context dict avait un objet en elle, à mon insu ...

Pour fixer, j'exécuté le code dépendant de la context avant l'appel async et vient de passer un dict avec seulement les types natifs:

def post_save(self, obj, created=False): 
    context = self.get_serializer_context() 
    clip_serializer = SolrClipSerializer(obj, context=context) 
    update_solr.delay(clip_serializer.data) 

la tâche a fini comme ceci:

@task 
def update_solr(data): 
    response = requests.post(url, data=data) 

cela fonctionne parfaitement bien parce que le seul but d'en faire une tâche async est pour rendre le POST non bloquant.

Merci pour l'aide!

0
import pickle 
class X: 
    def y(self): 
     pass 

pickle.dumps(X.y) 

Pickle fonctionne récursive de sorte qu'il pourrait être n'importe où dans votre objet graphique. Vous avez reçu la solution - ne transférer que les objets minimaux, c'est-à-dire les clés primaires et autres, à la place des objets du modèle Django.

+1

J'ai fait et obtiens toujours la même erreur. Je vais mettre à jour. – hamsterdam

1

Essayez de passer la clé primaire de l'instance de modèle (pk). Ceci est beaucoup plus simple à décaper, réduit la charge utile et évite les conditions de course.

+0

Terminé. Même erreur – hamsterdam

+0

Désolé - je pensais que vous avez dit qu'il a été réparé ;-) Avez-vous exécuté la méthode sans céleri? – AndrewS

+0

Je l'ai eu le travail, voir ma réponse. – hamsterdam

Questions connexes