Python 芹菜发现具有其他文件名的文件中的任务

Python 芹菜发现具有其他文件名的文件中的任务,python,django,celery,Python,Django,Celery,我开始有很多芹菜任务,我想把它们分解成更小的文件,而不是把它们放在一个大的tasks.py中,但我没有设法让芹菜发现它们 工作结构: proj/ app/ tasks.py 结构我想工作: proj/ app/ tasks/ __init__.py task1.py task2.py ... 但在这里芹菜找不到我的任务。我试着设置芹菜的导入,但是我必

我开始有很多芹菜任务,我想把它们分解成更小的文件,而不是把它们放在一个大的
tasks.py
中,但我没有设法让芹菜发现它们

工作结构:

proj/
    app/
        tasks.py
结构我想工作:

proj/
    app/
        tasks/
            __init__.py
            task1.py
            task2.py
            ...
但在这里芹菜找不到我的任务。我试着设置芹菜的导入,但是我必须指定每个文件,而且文件太多了。如果我将每个文件内容导入到
\uuuu init\uuuu.py
中,则相同。我希望自动查找所有任务,或者至少查找任务目录中文件中的所有任务

当然,我可以将每个任务目录中的所有文件都列在芹菜导入中,但这看起来相当难看


如果这是一个很好的方法,有什么想法吗?

我放弃了寻找一个很好的解决方案,而是编写了一个函数,我调用它并用它填充芹菜导入。这不好,但很管用

以下代码供将来参考:

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__))

我尝试了@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

这是一种肮脏的方式,但它可以工作。

芹菜默认为搜索任务的唯一原因。py是自动发现任务的默认参数:

./loaders/base.py:def autodiscover_tasks(packages, related_name='tasks'):
如果您使用文档推荐的配置,您只需调用autodiscover_tasks,对于您希望具有任务的不同文件名,相关_name的非默认值即可。例如,这里是我们的芹菜.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')
如果您的文件结构如上所述,则可以执行以下操作


您只需在
任务/\uuuuu init\uuuuuuuuuy.py
文件中定义
\uuuuuuu all\uuuuuuuuuu
。没有额外的芹菜设置更改

例如:

#app/tasks/uuu init_uuuu.py
从带有任务的.file\u导入任务1,任务2
from.file_与_任务_2导入任务3
__全部[
“任务1”,
“任务2”,
“任务3”,
]

在芹菜v4.4.6上测试

什么不适合你?我仍然在使用这个解决方案,对我来说没问题。我不能使用这个建议,因为这个项目是由一堆应用程序组成的,每个应用程序可能都有自己的tasks文件夹,其中包含无限的python文件和任务,所以我希望它更具动态性。这是旧的,但适用于芹菜的新版本(例如:芹菜v3.1.18)。这并不能解决我最初的问题。我想通过多个应用程序自动注册分布在名为tasks的文件夹中的100个文件。我必须为每个文件编写
related_name='tasks.task1'
,因此这是一个很好的技巧,但对最初的问题没有帮助。如果您将其放入设置中,它将在每次请求时运行,并从硬盘驱动器读取。或者我遗漏了什么?我不记得是否每次都读取设置,如果是这样,缓存或记忆将起作用。不会为每个请求重新加载设置。它在芹菜工人开始时导入一次,必须将其标记为已接受答案
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)