2014-02-27 8 views
5

Ich fange an, so viele Sellerieaufgaben zu haben, dass ich sie in kleinere Dateien zerbrechen will, anstatt sie in einem großen tasks.py zu haben, aber ich schaffe es nicht, Sellerie zu bekommen entdecke sie.Sellerie entdecken Aufgaben in Dateien mit anderen Dateinamen

Arbeitsstruktur:

proj/ 
    app/ 
     tasks.py 

Struktur Ich mag würde arbeiten:

proj/ 
    app/ 
     tasks/ 
      __init__.py 
      task1.py 
      task2.py 
      ... 

Aber hier Sellerie findet nicht meine Aufgaben. Ich habe versucht, die CELERY_IMPORTS zu setzen, aber dann muss ich jede Datei angeben, und es gibt so viele Dateien. Gleiches, wenn ich jeden Dateiinhalt in __init__.py importiere. Ich möchte, dass alle Aufgaben automatisch erkannt werden, oder zumindest alle Aufgaben in Dateien im Aufgabenverzeichnis.

Ich könnte natürlich alle Dateien in jedem Aufgabenverzeichnis in CELLERY_IMPORTS auflisten, aber das scheint ziemlich hässlich.

Irgendwelche Ideen, wenn das auf eine nette Art möglich ist?

+0

diese alte, aber arbeitet mit neueren Versionen fein von Sellerie (zB: Sellerie v3.1.18) – Rafael

Antwort

2

Ich habe es aufgegeben, eine gute Lösung zu finden und habe stattdessen eine Funktion geschrieben, die ich anrufe und CELLERY_IMPORTS bevölkere. Es ist nicht nett, aber es funktioniert.

Hier ist der Code für die Zukunft:

import os 

def detect_tasks(project_root): 
    tasks = [] 
    file_path = os.path.join(project_root, 'apps') 
    for root, dirs, files in os.walk(file_path): 
     for filename in files: 
      if os.path.basename(root) == 'tasks': 
       if filename != '__init__.py' and filename.endswith('.py'): 
        task = os.path.join(root, filename)\ 
         .replace(os.path.dirname(project_root) + '/', '')\ 
         .replace('/', '.')\ 
         .replace('.py', '') 
        tasks.append(task) 
    return tuple(tasks) 

Und dann in den Einstellungen:

CELERY_IMPORTS = detect_tasks(project_root) 

Wo project_root etwas so sein würde:

project_root = os.path.dirname(os.path.abspath(__file__)) 
+0

Wenn Sie es in den Einstellungen setzen, wird es bei jeder Anfrage ausgeführt und liest die Festplatte. Oder fehlt mir etwas? –

+0

Ich erinnere mich nicht, wenn Einstellungen jedes Mal gelesen werden, wenn so Cache oder Memoize es funktionieren würde. – olofom

0

I-Code-Schnipsel versucht, aus @oLoform. Es funktioniert nicht für mich. Ich habe eine sehr einfache Idee. Da Sellerie nach tasks.py für irgendwelche Aufgaben sucht. Ich definiere Aufgaben in jeder Datei, aber ich bin das Hinzufügen es in tasks.py wie

# tasks.py 
from app.utilities.somename import upload_done 
from project.celery import app 
app.task(upload_done) 

Es ist leicht in Sellerie Protokollen sichtbar ist,

-------------- [email protected]######## v3.1.18 (Cipater) 
---- **** ----- 
--- * *** * -- ############### 
-- * - **** --- 
- ** ---------- [config] 
- ** ---------- .> app:   project:0x2aae5c0 
- ** ---------- .> transport: django://localhost// 
- ** ---------- .> results:  djcelery.backends.database:DatabaseBackend 
- *** --- * --- .> concurrency: 4 (prefork) 
-- ******* ---- 
--- ***** ----- [queues] 
-------------- .> celery   exchange=celery(direct) key=celery 


[tasks] 
    . app.utilities.somename.upload_done 

Es ist schmutzig Art und Weise aber, es funktioniert.

+0

Was funktioniert nicht für dich? Ich benutze immer noch die Lösung und für mich ist es in Ordnung. Ich kann diesen Vorschlag nicht verwenden, da das Projekt aus einer Reihe von Apps besteht und jede App einen eigenen Aufgabenordner mit unbegrenzten Python-Dateien mit Aufgaben in sich hat, also wollte ich es dynamischer gestalten. – olofom

2

Der einzige Grund, dass Sellerie defaults tasks.py auf der Suche das Argument autodiscover_tasks Standard ist:

./loaders/base.py:def autodiscover_tasks(packages, related_name='tasks'): 

Wenn Sie die Konfiguration durch die docs empfohlen verwenden Sie nur autodiscover_tasks mit Nicht-Standardwerte für related_name aufrufen für die verschiedenen Dateinamen, in denen Sie Aufgaben erwarten. Zum Beispiel ist hier unsere celery.py:

from __future__ import absolute_import 

import os 

from celery import Celery 

# set the default Django settings module for the 'celery' program. 
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") 

from django.conf import settings 

app = Celery('app') 

# Using a string here means the worker will not have to 
# pickle the object when using Windows. 
app.config_from_object('django.conf:settings') 
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) 
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, related_name='tasks2') 
+2

Das löst meine anfängliche Frage nicht. Ich möchte 100 Dateien, die in Ordnern namens "Aufgaben" verteilt sind, automatisch über mehrere Apps registrieren. Ich müsste für jede Datei 'related_name = 'tasks.task1'' schreiben, also ist es ein netter Tipp, aber es hilft nicht bei der ersten Frage. – olofom

0
proj/ 
    app/ 
     tasks/ 
      __init__.py 
      task1.py 
      task2.py 
      ... 

wenn Ihre Dateien Struktur wie oben, können Sie wie folgt

import os 
from celery import Celery 
from django.conf import settings 

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') 

app = Celery('celery') 
app.config_from_object('django.conf:settings', namespace='CELERY') 

for app_name in settings.INSTALLED_APPS: 
    if app_name.startswith('django'): 
     continue 
    for root, dirs, files in os.walk(app_name + '/tasks'): 
     for file in files: 
      if file.startswith('__') or file.endswith('.pyc') or not file.endswith('.py'): 
       continue 
      file = file[:-3] 
      app.autodiscover_tasks([app_name + '.tasks'], related_name=file) 
Verwandte Themen