我开始有这么多芹菜任务,我想将它们分解成较小的文件而不是将它们放在一个大的tasks.py
中,但我无法让芹菜去发现它们。 / p>
工作结构:
proj/
app/
tasks.py
结构我想工作:
proj/
app/
tasks/
__init__.py
task1.py
task2.py
...
但芹菜在这里找不到我的任务。我尝试设置CELERY_IMPORTS,但后来我必须指定每个文件,并且文件太多了。如果我将每个文件内容导入__init__.py
,则相同。我希望自动发现所有任务,或者至少任务目录中的文件中的所有任务。
我当然可以将每个任务目录中的所有文件列入CELERY_IMPORTS,但这看起来相当丑陋。
任何想法,如果这可能是一个很好的方式吗?
答案 0 :(得分:4)
您可以在 __all__
文件中定义 tasks/__init__.py
。无需更改 celery 设置。
例如:
# app/tasks/__init__.py
from .file_with_tasks_1 import task1, task2
from .file_with_tasks_2 import task3
__all__ = [
'task1',
'task2',
'task3',
]
在 celery v4.4.6 上测试
答案 1 :(得分:3)
我放弃了找到一个很好的解决方案,而是编写了一个我调用并填充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__))
答案 2 :(得分:3)
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)
答案 3 :(得分:2)
celery默认搜索tasks.py的唯一原因是autodiscover_tasks的默认参数:
./loaders/base.py:def autodiscover_tasks(packages, related_name='tasks'):
如果您使用文档建议的配置,则只需为您希望具有任务的不同文件名调用具有related_name的非默认值的autodiscover_tasks。例如,这是我们的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')
答案 4 :(得分:0)
我尝试了@oloform的代码片段。它不适合我。我有一个非常简单的想法。因为芹菜会为任何任务寻找tasks.py。我在任何文件中定义任务,但我将其添加到tasks.py中,如
# tasks.py
from app.utilities.somename import upload_done
from project.celery import app
app.task(upload_done)
在芹菜原木中很容易看到,
-------------- celery@######## 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
这是肮脏的方式但它有效。