2014-02-27 39 views
5

我開始有這麼多的芹菜任務,我想把它們分解成更小的文件,而不是讓它們在大的tasks.py,但我沒有設法讓芹菜發現他們。芹菜在其他文件名的文件中發現任務

工作結構:

proj/ 
    app/ 
     tasks.py 

結構我想工作:

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

但這裏芹菜沒有找到我的任務。我嘗試設置CELERY_IMPORTS,但是之後我必須指定每個文件,並且有很多文件。如果我將每個文件內容導入__init__.py,也是一樣。我希望自動發現所有任務,或者至少完成任務目錄中文件的所有任務。

我當然可以列出每個任務目錄中的所有文件到CELERY_IMPORTS中,但看起來相當難看。

任何想法,如果這是可能的一個很好的方式?

+0

這是舊的,但正常工作與新版本芹菜(例如:芹菜v3.1。18) – Rafael

回答

2

我放棄尋找一個很好的解決方案,而是寫了一個函數,我調用並填充CELERY_IMPORTS。這不好,但它的工作原理。

這裏以供將來參考代碼:

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) 

然後在設置:

CELERY_IMPORTS = detect_tasks(project_root) 

凡project_root會是這樣的:

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

如果你把它放在它將在每個請求上運行的設置中,並且將從硬盤讀取數據。 或者我錯過了什麼? –

+0

我不記得是否每次讀取設置,如果這樣緩存或記憶它會工作。 – olofom

0

我試圖從代碼片段@oloform。它不適合我。我有一個非常簡單的想法。由於芹菜爲任何任務尋找tasks.py。我定義任務中的任何文件,但我加入它tasks.py一樣,

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

它在芹菜日誌很容易看到,

-------------- [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 

這是骯髒的方式,但是,它的工作原理。

+0

什麼不適合你?我仍然在使用這個解決方案,對我來說沒問題。我不能使用這個建議,因爲該項目是由一堆應用程序構建的,每個應用程序可能都有自己的任務文件夾,其中包含任務的無限python文件,因此我希望它更具動態性。 – olofom

2

的唯一原因,芹菜默認搜索tasks.py是默認參數autodiscover_tasks:

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

如果您使用的文檔推薦的配置,你可以叫autodiscover_tasks與related_name非默認值對於您希望執行任務的不同文件名稱。例如這裏是我們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

這並不能解決我最初的問題。我想在多個應用程序中自動註冊分佈在名爲任務的文件夾中的100個文件。我不得不爲每個文件寫'related_name ='tasks.task1'',所以這是一個很好的提示,但它對最初的問題沒有幫助。 – olofom

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

如果如上述文件的結構,你可以做以下

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)