Celery中文翻译-Application

栏目: 后端 · 发布时间: 6年前

内容简介:Celery在使用前必须实例化,称为application或app。app是线程安全的,具有不同配置、组件、task的多个Celery应用可以在同一个进程空间共存。最后一行文本化显示了Celery应用:包含应用所属类的名称,当前主模块名,以及内存地址。唯一重要的信息是模块名称。在Celery中发送task消息时,该消息仅包含要执行的task的名称。每一个worker维护一个task名称和对应函数的映射,这称为

Celery在使用前必须实例化,称为application或app。app是线程安全的,具有不同配置、组件、task的多个Celery应用可以在同一个进程空间共存。

# 创建Celery应用
>>> from celery import Celery
>>> app = Celery()
>>> app
<Celery __main__:0x100469fd0>

最后一行文本化显示了Celery应用:包含应用所属类的名称,当前主模块名,以及内存地址。唯一重要的信息是模块名称。

Main Name

在Celery中发送task消息时,该消息仅包含要执行的task的名称。每一个worker维护一个task名称和对应函数的映射,这称为 task registry

当定义一个task时,该task将注册到本地:

>>> @app.task
... def add(x, y):
...     return x + y

>>> add
<@task: __main__.add>

>>> add.name
__main__.add

>>> app.tasks['__main__.add']
<@task: __main__.add>

当Celery无法检测task函数属于哪个模块时,使用main模块名生成初始task名称。

这种方式仅适用于以下两种场景:

  1. 定义task的模块作为程序运行
  2. app在python shell中创建
# tasks.py
from celery import Celery
app = Celery()

@app.task
def add(x, y): return x + y

if __name__ == '__main__':
    app.worker_main()

如果直接运行tasks.py,task名将以 __main__ 为前缀,但如果tasks.py被其他程序导入,task名将以 tasks 为前缀。如下:

>>> from tasks import add
>>> add.name
tasks.add

也可以直接指定主模块名:

>>> app = Celery('tasks')
>>> app.main
'tasks'

>>> @app.task
... def add(x, y):
...     return x + y

>>> add.name
tasks.add

Configuration

可以通过直接设置,或使用专用配置模块对Celery进行配置。

通过 app.conf 属性查看或直接设置配置:

>>> app.conf.timezone
'Europe/London'

>>> app.conf.enable_utc = True

或用 app.conf.update 方法一次更新多个配置:

>>> app.conf.update(
...     enable_utc=True,
...     timezone='Europe/London',
...)

config_from_object

app.config_from_object() 方法从配置模块或对象中导入配置。需要注意的是: 调用config_from_object()方法将重置在这之前配置的任何设置

使用模块名

app.config_from_object()方法接收 python 模块的完全限定名( fully qualified name )或具体到其中的某个属性名,例如"celeryconfig", "myproj.config.celery", 或"myproj.config:CeleryConfig":

from celery import Celery

app = Celery()
app.config_from_object('celeryconfig')

只要能够正常执行 import celeryconfig ,app就能正常配置。

使用模块对象

也可以传入一个已导入的模块对象,但不建议这样做。

import celeryconfig

from celery import Celery

app = Celery()
app.config_from_object(celeryconfig)

更推荐使用模块名的方式,因为这样在使用prefork pool时不需要序列化该模块。如果在实际应用中出现配置问题或序列化错误,请尝试使用模块名的方式。

使用配置类或对象

from celery import Celery

app = Celery()

class Config:
    enable_utc = True
    timezone = 'Europe/London'

app.config_from_object(Config)

config_from_envvar

app.config_from_envvar() 方法从环境变量中接收配置模块名。

import os
from celery import Celery

#: Set default configuration module name
os.environ.setdefault('CELERY_CONFIG_MODULE', 'celeryconfig')

app = Celery()
app.config_from_envvar('CELERY_CONFIG_MODULE')

通过环境变量指定配置模块:

$ CELERY_CONFIG_MODULE="celeryconfig.prod" celery worker -l info

Censored configuration

如果要显示Celery配置,可能需要过滤某些敏感信息如密码、密钥等。Celery提供了几种用于帮助显示配置的实用方法。

humanize()

该方法返回列表字符串形式的配置,默认只包含改动过的配置,如果要显示内置的默认配置,设置 with_defaults 参数为True:

>>> app.conf.humanize(with_defaults=False, censored=True)

table()

该方法返回字典形式的配置:

>>> app.conf.table(with_defaults=False, censored=True)

Celery可能不会移除所有的敏感信息,因为它使用正则表达式匹配键并判断是否移除。如果用户添加了包含敏感信息的自定义配置,可以使用Celery可能标记为敏感配置的名称来命名(API, TOKEN, KEY, SECRET, PASS, SIGNATURE, DATABASE)。

Laziness

应用实例是惰性的。

创建Celery实例只会执行以下操作:

logical clock instance
task registry
set_as_current
app.on_init()

app.task() 装饰器不会在task定义时立即创建task,而是在task使用时或 finalized 应用后创建。

下例说明了在使用task或访问其属性前,都不会创建task:

>>> @app.task
>>> def add(x, y):
...    return x + y

>>> type(add)
<class 'celery.local.PromiseProxy'>

>>> add.__evaluated__()
False

>>> add        # <-- causes repr(add) to happen
<@task: __main__.add>

>>> add.__evaluated__()
True

应用的 Finalization 指显式地调用 app.finalize() 方法或隐式地访问app.tasks属性。

finalized 应用将会:

shared

Breaking the chain

虽然可以依赖于当前应用,但最佳实践是将应用实例传递给任何需要它的对象,这个行为可以称为 app chain

# 依赖于当前应用(bad)

from celery import current_app

class Scheduler(object):

    def run(self):
        app = current_app
# 传递应用实例(good)

class Scheduler(object):

    def __init__(self, app):
        self.app = app

在开发模式设置CELERY_TRACE_APP环境变量,可以在应用链断开时抛出异常:

$ CELERY_TRACE_APP=1 celery worker -l info

Abstract Tasks

使用 task() 装饰器创建的task都继承自 celery.app.task 模块的 Task 基类。继承该类可以自定义task类:

from celery import Task
# 或者 from celery.app.task import Task

class DebugTask(Task):

    def __call__(self, *args, **kwargs):
        print('TASK STARTING: {0.name}[{0.request.id}]'.format(self))
        return super(DebugTask, self).__call__(*args, **kwargs)

如果要重写 __call__() 方法,记得调用super。这样在task直接调用时会执行基类的默认事件。

Task 基类是特殊的,因为它并未绑定到任何特定的应用。一旦task绑定到应用,它将读取配置以设置默认值等。

  1. 通过 base 参数指定基类

    @app.task(base=DebugTask)
    def add(x, y):
        return x + y
  2. 通过 app.Task 属性指定基类

    >>> from celery import Celery, Task
    
    >>> app = Celery()
    
    >>> class MyBaseTask(Task):
    ...    queue = 'hipri'
    
    >>> app.Task = MyBaseTask
    >>> app.Task
    <unbound MyBaseTask>
    
    >>> @app.task
    ... def add(x, y):
    ...     return x + y
    
    >>> add
    <@task: __main__.add>
    
    >>> add.__class__.mro()
    [<class add of <Celery __main__:0x1012b4410>>,
     <unbound MyBaseTask>,
     <unbound Task>,
     <type 'object'>]

以上所述就是小编给大家介绍的《Celery中文翻译-Application》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Realm of Racket

Realm of Racket

Matthias Felleisen、Conrad Barski M.D.、David Van Horn、Eight Students Northeastern University of / No Starch Press / 2013-6-25 / USD 39.95

Racket is the noble descendant of Lisp, a programming language renowned for its elegance and power. But while Racket retains the functional goodness of Lisp that makes programming purists drool, it wa......一起来看看 《Realm of Racket》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具