le céleri tâche et de personnaliser décorateur
Je suis en train de travailler sur un projet à l'aide de django et de céleri(django-céleri). Notre équipe a décidé d'envelopper tout le code d'accès aux données à l'intérieur de (app-name)/manager.py
(PAS envelopper dans les Gestionnaires comme les django
façon), et laissez-code (app-name)/task.py seulement affaire avec les assembler et de les exécuter des tâches de céleri(si nous n'avons pas l'ORM de django dépendance dans cette couche).
Dans mon manager.py
, j'ai quelque chose comme ceci:
def get_tag(tag_name):
ctype = ContentType.objects.get_for_model(Photo)
try:
tag = Tag.objects.get(name=tag_name)
except ObjectDoesNotExist:
return Tag.objects.none()
return tag
def get_tagged_photos(tag):
ctype = ContentType.objects.get_for_model(Photo)
return TaggedItem.objects.filter(content_type__pk=ctype.pk, tag__pk=tag.pk)
def get_tagged_photos_count(tag):
return get_tagged_photos(tag).count()
Dans mon task.py, j'aime bien les envelopper dans des tâches (alors peut-être utiliser ces tâches à effectuer des tâches plus complexes), alors j'écris ce décorateur:
import manager #the module within same app containing data access functions
class mfunc_to_task(object):
def __init__(mfunc_type='get'):
self.mfunc_type = mfunc_type
def __call__(self, f):
def wrapper_f(*args, **kwargs):
callback = kwargs.pop('callback', None)
mfunc = getattr(manager, f.__name__)
result = mfunc(*args, **kwargs)
if callback:
if self.mfunc_type == 'get':
subtask(callback).delay(result)
elif self.mfunc_type == 'get_or_create':
subtask(callback).delay(result[0])
else:
subtask(callback).delay()
return result
return wrapper_f
ensuite (toujours dans task.py
):
#@task
@mfunc_to_task()
def get_tag():
pass
#@task
@mfunc_to_task()
def get_tagged_photos():
pass
#@task
@mfunc_to_task()
def get_tagged_photos_count():
pass
Les choses fonctionnent très bien sans @task
.
Mais, après l'application de cette @task
décorateur(vers le haut comme le céleri chargé de la documentation), les choses commencent à tomber en morceaux. Apparemment, chaque fois que le mfunc_to_task.__call__
est appelée, le même task.get_tag
fonction reçoit comme f
. Je me suis donc retrouvé avec le même wrapper_f
tous les temps, et maintenant, la seule chose que je chat faire est d'obtenir une balise unique.
Je suis nouveau sur les décorateurs. Quelqu'un peut m'aider à comprendre ce qui s'est passé ici, ou point d'autres moyens pour réaliser la tâche? J'ai vraiment hate d'écrire la même tâche envelopper code pour chaque de mes fonctions d'accès aux données.
OriginalL'auteur zxygentoo | 2011-06-18
Vous devez vous connecter pour publier un commentaire.
Pas très bien pourquoi le passage d'arguments ne fonctionne pas?
si vous utilisez cet exemple:
permet d'ajouter un peu de journalisation pour le MyCoolTask:
et de créer une classe étendue (extension de MyCoolTask, mais maintenant, avec des arguments):
et assurez-vous de passer le kwargs que les données json:
- Je obtenir le résultat:
TypeError: __init__() takes exactly 3 arguments (1 given)
. En va de même lorsque l'on essaie de faire une fonction séparée avec la tâche décorateur@app.task(bind=True, base=AddTask)
, comme indiqué ici. La seule option que je connaisse est de créer une instance de la classe avant de l'enregistrer. Est-il un autre moyen similaire à ce qu'on fait ici?oui, oui, c'était un post de 2013 .... Il y a 5 ans.... beaucoup a changé depuis que. Je peux voir si je peux produire un meilleur exemple avec le céleri 4.0. Pouvez-vous définir une nouvelle question? Je suis loin de classe basée sur les tâches.... en fin de compte n'a pas fonctionné pour moi. Je suis en utilisant le @shared_task seulement aujourd'hui....
OriginalL'auteur michel.iamit
Au lieu d'utiliser décorateur pourquoi ne pas créer une classe de base qui s'étendent
celery.Task
?De cette façon, toutes vos tâches permet d'élargir votre tâche personnalisé de classe, où vous pouvez mettre en œuvre votre comportement personnel en utilisant des méthodes
__call__
etafter_return
.
Vous pouvez également définir des méthodes communes et l'objet de toutes vos tâches.
Sincèrement je pense que c'est assez élégant. Un personnel suggestion est que, quand vous ne pouvez pas trouver une solution élégante, probablement, de toute approche est erronée. Mais il est possible que je me trompe ;-), à vous de voir
merci pour votre réponse et dans l'explication claire des europycon 2011 présentation sur youtube, cela me conduire (après déroutant un peu plus) à la réponse que j'ai donné ici. (voir: slideshare.net/fireantology/...)
OriginalL'auteur Mauro Rocco