代码贡献者指南 — Python 文档

来自菜鸟教程
Celery/docs/latest/internals/guide
跳转至:导航、​搜索

代码贡献者指南

哲学

API>RCP 优先规则

  • API 比可读性更重要
  • 可读性比约定更重要
  • *; 约定比性能更重要
    *;* ...除非代码是一个经过验证的热点。

最重要的是最终用户 API。 惯例必须搁置一旁,如果最终结果是更好的 API,则任何痛苦总是可以减轻的。


使用的约定和习语

班级

命名

  • 遵循 PEP 8

  • 类名必须是 CamelCase。

  • 但不是如果它们是动词,动词应为 lower_case:

    # - test case for a class
    class TestMyClass(Case):                # BAD
        pass
    
    class test_MyClass(Case):               # GOOD
        pass
    
    # - test case for a function
    class TestMyFunction(Case):             # BAD
        pass
    
    class test_my_function(Case):           # GOOD
        pass
    
    # - "action" class (verb)
    class UpdateTwitterStatus:    # BAD
        pass
    
    class update_twitter_status:    # GOOD
        pass

    笔记

    有时将类掩码作为函数是有意义的,并且在 Python 标准库中有优先级(例如,contextmanager)。 Celery 示例包括 signaturechordinspectpromise 等等。

  • 工厂函数和方法必须是 CamelCase(不包括动词):

    class Celery:
    
        def consumer_factory(self):     # BAD
            ...
    
        def Consumer(self):             # GOOD
            ...


默认值

类属性用作实例的默认值,因为这意味着它们可以通过实例化或继承来设置。

例子:

class Producer:
    active = True
    serializer = 'json'

    def __init__(self, serializer=None, active=None):
        self.serializer = serializer or self.serializer

        # must check for None when value can be false-y
        self.active = active if active is not None else self.active

子类可以更改默认值:

TaskProducer(Producer):
    serializer = 'pickle'

并且可以在实例化时设置该值:

>>> producer = TaskProducer(serializer='msgpack')

例外

由对象方法和属性引发的自定义异常应作为属性提供,并记录在抛出的方法/属性中。

这样用户就不必找出从哪里导入异常,而是使用 help(obj) 并直接从实例访问异常类。

示例

class Empty(Exception):
    pass

class Queue:
    Empty = Empty

    def get(self):
        """Get the next item from the queue.

        :raises Queue.Empty: if there are no more items left.

        """
        try:
            return self.queue.popleft()
        except IndexError:
            raise self.Empty()

复合材料

与异常类似,复合类应该可以通过继承和/或实例化来覆盖。 在选择要包含的类时可以使用常识,但通常最好添加一个太多:预测用户需要覆盖的内容是困难的(这使我们免于许多猴子补丁)。

示例

class Worker:
    Consumer = Consumer

    def __init__(self, connection, consumer_cls=None):
        self.Consumer = consumer_cls or self.Consumer

    def do_work(self):
        with self.Consumer(self.connection) as consumer:
            self.connection.drain_events()

应用程序对比 “单一模式”

最初 Celery 是为 Django 开发的,仅仅是因为这使我们能够快速启动项目,同时还拥有庞大的潜在用户群。

在 Django 中,有一个全局设置对象,因此多个 Django 项目不能在同一个进程空间中共存,这给后来在没有这个限制的框架中使用 Celery 带来了问题。

因此引入了应用程序概念。 使用应用程序时,您使用“celery”对象而不是从 Celery 子模块导入内容,这(不幸的是)也意味着 Celery 本质上有两个 API。

这是在单模式下使用 Celery 的示例:

from celery import task
from celery.task.control import inspect

from .models import CeleryStats

@task
def write_stats_to_db():
    stats = inspect().stats(timeout=1)
    for node_name, reply in stats:
        CeleryStats.objects.update_stat(node_name, stats)

使用 Celery 应用程序对象也是如此:

from .celery import celery
from .models import CeleryStats

@app.task
def write_stats_to_db():
    stats = celery.control.inspect().stats(timeout=1)
    for node_name, reply in stats:
        CeleryStats.objects.update_stat(node_name, stats)

在上面的示例中,实际应用程序实例是从项目中的模块导入的,该模块可能如下所示:

from celery import Celery

app = Celery(broker='amqp://')

模块概述

  • celery.app

    这是 Celery 的核心:所有功能的入口点。

  • celery.loaders

    每个应用程序都必须有一个加载器。 加载器决定如何读取配置; 工人开始时会发生什么; 任务何时开始和结束; 等等。

    包括的装载机是:

    • 应用程序

      默认情况下,自定义 Celery 应用程序实例使用此加载程序。

    • 默认

      “单模式”默认使用这个加载器。


    也存在扩展加载器,例如 :pypi:`celery-pylons`

  • 芹菜工人

    这是工作人员的实现。

  • celery.backends

    任务结果后端在这里。

  • celery.apps

    主要用户应用:worker 和 beat。 这些的命令行包装器在 celery.bin 中(见下文)

  • celery.bin

    命令行应用程序。 setup.py 为这些创建 setuptools 入口点。

  • celery.concurrency

    执行池实现(prefork、eventlet、gevent、solo、thread)。

  • 芹菜数据库

    SQLAlchemy 数据库结果后端的数据库模型。 (应移入celery.backends.database

  • celery.events

    发送和使用监控事件,还包括curses 监控器、事件转储器和用于处理内存集群状态的实用程序。

  • celery.execute.trace

    工作人员如何在急切模式下执行和跟踪任务。

  • celery.security

    安全相关功能,目前是使用加密摘要的序列化程序。

  • celery.task

    用于创建任务和控制工作人员的单模式界面。

  • t.unit(整数分布)

    单元测试套件。

  • celery.utils

    Celery 代码库使用的实用函数。 其中大部分是为了跨 Python 版本兼容。

  • celery.contrib

    不适合任何其他名称空间的其他公共代码。


工人概览

  • celery.bin.worker: 工人

    这是工作人员的命令行界面。

    职责:
    • 设置 --detach 时的守护进程,

    • 使用 --uid/--gid 参数时删除权限

    • 安装“并发补丁”(eventlet/gevent 猴子补丁)。


    app.worker_main(argv) 调用 instantiate('celery.bin.worker:Worker')(app).execute_from_commandline(argv)

  • app.Worker -> celery.apps.worker:Worker

    职责: * 设置日志记录和重定向标准输出 * 安装信号处理程序(TERM/HUP/STOP/USR1(哭)/ USR2 (rdb)) * 打印横幅和警告(例如,pickle 警告) * 处理 celery worker --purge 参数

  • app.WorkController -> celery.worker.WorkController

    这是真正的工人,围绕着bootsteps 建立起来。