Je voulais appeler des tâches de manière synchrone (et non asynchrone) dans un projet Django + Celery pour voir comment elles fonctionnent. Je l'ai écrit parce que je pensais qu'il serait facile de spécifier une tâche et de l'appeler à partir de la commande de gestion de Django.
Placez les fichiers suivants sous gestion / commandes / de l'application.
run_task.py
import importlib
import inspect
import json
import pdb
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "Django commands that make debugging celery tasks easier"
def add_arguments(self, parser):
parser.add_argument(
"dottedname", help="The dotted name of the callable object."
)
parser.add_argument(
"--task-args",
default="[]",
type=json.loads,
help="Arguments passed to the task. (default: '[]')",
)
parser.add_argument(
"--task-kwargs",
default="{}",
type=json.loads,
help="Keyword arguments passed to the task. (default: '{}')",
)
parser.add_argument(
"--pdb", action="store_true", help="Stop execution by debugger."
)
parser.add_argument(
"--pdb-offset",
default=0,
type=int,
help="Offset for debugger to create breakpoint. (default: 0)",
)
def handle(self, **options):
dotted_list = options["dottedname"].strip().split(".")
module_name = ".".join(dotted_list[:-1])
func_name = dotted_list[-1]
try:
module = importlib.import_module(module_name)
except ModuleNotFoundError:
self.stderr.write(f"No module: {module_name}")
return
try:
func = getattr(module, func_name)
except AttributeError:
self.stderr.write(f"No attribute: {func_name} not in {module_name}")
return
if not callable(func):
self.stderr.write(f"Not function: {module_name}.{func_name}")
return
if options["pdb"]:
lineno = inspect.getsourcelines(func)[1] + options["pdb_offset"]
debugger = pdb.Pdb()
debugger.set_break(module.__file__, lineno=lineno, funcname=func_name)
debugger.set_trace()
result = func(*options["task_args"], **options["task_kwargs"])
self.stdout.write(f"Return: {json.dumps(result)}")
Si tu l'appelles comme ça
$ python manage.py run_task myproject.tasks.example_task --task-args '[1, 2, 3]'
Il se comporte de la même manière que l'appeler ainsi.
>>> from myproject.tasks import example_task
>>> example_task(1, 2, 3)
J'ai également essayé de démarrer le débogueur en spécifiant --pdb
.
$ python manage.py run_task myproject.tasks.example_task --pdb --task-args '[1, 2, 3]'
Ensuite, le débogueur démarre avec le point d'arrêt défini dans myproject.tasks.example_task. Je l'ai écrit pour le titre, mais Celery n'avait pas vraiment d'importance.
Mettez-le dans l'essentiel. https://gist.github.com/TakesxiSximada/d986ef7d8fbf5555d8e12586226dc389
Recommended Posts