摘要:在使用前必須實(shí)例化,稱為或。在中發(fā)送消息時(shí),該消息僅包含要執(zhí)行的的名稱。每一個(gè)維護(hù)一個(gè)名稱和對(duì)應(yīng)函數(shù)的映射,這稱為。雖然可以依賴于當(dāng)前應(yīng)用,但最佳實(shí)踐是將應(yīng)用實(shí)例傳遞給任何需要它的對(duì)象,這個(gè)行為可以稱為。
Celery在使用前必須實(shí)例化,稱為application或app。app是線程安全的,具有不同配置、組件、task的多個(gè)Celery應(yīng)用可以共存于同一個(gè)進(jìn)程空間。
# 創(chuàng)建Celery應(yīng)用 >>> from celery import Celery >>> app = Celery() >>> app
最后一行文本化顯示了Celery應(yīng)用:包含應(yīng)用所屬類的名稱,當(dāng)前主模塊名,以及內(nèi)存地址。唯一重要的信息是模塊名稱。
Main Name在Celery中發(fā)送task消息時(shí),該消息僅包含要執(zhí)行的task的名稱。每一個(gè)worker維護(hù)一個(gè)task名稱和對(duì)應(yīng)函數(shù)的映射,這稱為task registry。
當(dāng)定義一個(gè)task時(shí),該task將注冊(cè)到本地:
>>> @app.task ... def add(x, y): ... return x + y >>> add <@task: __main__.add> >>> add.name __main__.add >>> app.tasks["__main__.add"] <@task: __main__.add>
當(dāng)Celery無(wú)法檢測(cè)task函數(shù)屬于哪個(gè)模塊時(shí),使用main模塊名生成初始task名稱。
這種方式僅適用于以下兩種場(chǎng)景:
定義task的模塊作為程序運(yùn)行
app在python shell中創(chuàng)建
# tasks.py from celery import Celery app = Celery() @app.task def add(x, y): return x + y if __name__ == "__main__": app.worker_main()
如果直接運(yùn)行tasks.py,task名將以__main__為前綴,但如果tasks.py被其他程序?qū)?,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.addConfiguration
可以通過(guò)直接設(shè)置,或使用專用配置模塊對(duì)Celery進(jìn)行配置。
通過(guò)app.conf屬性查看或直接設(shè)置配置:
>>> app.conf.timezone "Europe/London" >>> app.conf.enable_utc = True
或用app.conf.update方法一次更新多個(gè)配置:
>>> app.conf.update( ... enable_utc=True, ... timezone="Europe/London", ...)config_from_object
app.config_from_object()方法從配置模塊或?qū)ο笾袑?dǎo)入配置。需要注意的是:調(diào)用config_from_object()方法將重置在這之前配置的任何設(shè)置。
使用模塊名
app.config_from_object()方法接收python模塊的完全限定名(fully qualified name)或具體到其中的某個(gè)屬性名,例如"celeryconfig", "myproj.config.celery", 或"myproj.config:CeleryConfig":
from celery import Celery app = Celery() app.config_from_object("celeryconfig")
只要能夠正常執(zhí)行import celeryconfig,app就能正常配置。
使用模塊對(duì)象
也可以傳入一個(gè)已導(dǎo)入的模塊對(duì)象,但不建議這樣做。
import celeryconfig from celery import Celery app = Celery() app.config_from_object(celeryconfig)
更推薦使用模塊名的方式,因?yàn)檫@樣在使用prefork pool時(shí)不需要序列化該模塊。如果在實(shí)際應(yīng)用中出現(xiàn)配置問(wèn)題或序列化錯(cuò)誤,請(qǐng)嘗試使用模塊名的方式。
使用配置類或?qū)ο?/strong>
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()方法從環(huán)境變量中接收配置模塊名。
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")
通過(guò)環(huán)境變量指定配置模塊:
$ CELERY_CONFIG_MODULE="celeryconfig.prod" celery worker -l infoCensored configuration
如果要顯示Celery配置,可能需要過(guò)濾某些敏感信息如密碼、密鑰等。Celery提供了幾種用于幫助顯示配置的實(shí)用方法。
humanize()
該方法按行返回字符串形式的配置,默認(rèn)只包含改動(dòng)過(guò)的配置,如果要顯示內(nèi)置的默認(rèn)配置,設(shè)置with_defaults參數(shù)為T(mén)rue:
>>> app.conf.humanize(with_defaults=False, censored=True)
table()
該方法返回字典形式的配置:
>>> app.conf.table(with_defaults=False, censored=True)
Celery不會(huì)移除所有的敏感信息,因?yàn)樗褂谜齽t表達(dá)式匹配鍵并判斷是否移除。如果用戶添加了包含敏感信息的自定義配置,可以使用Celery可能標(biāo)記為敏感配置的名稱來(lái)命名(API, TOKEN, KEY, SECRET, PASS, SIGNATURE, DATABASE)。
Laziness應(yīng)用實(shí)例是惰性的。
創(chuàng)建Celery實(shí)例只會(huì)執(zhí)行以下操作:
創(chuàng)建用于event的logical clock instance
創(chuàng)建task registry
設(shè)置為當(dāng)前應(yīng)用(除非禁用了set_as_current參數(shù))
調(diào)用app.on_init()回調(diào)函數(shù)(默認(rèn)不執(zhí)行任何操作)
app.task()裝飾器不會(huì)在task定義時(shí)立即創(chuàng)建task,而是在task使用時(shí)或finalized應(yīng)用后創(chuàng)建。
下例說(shuō)明了在使用task或訪問(wèn)其屬性前,都不會(huì)創(chuàng)建task:
>>> @app.task >>> def add(x, y): ... return x + y >>> type(add)>>> add.__evaluated__() False >>> add # <-- causes repr(add) to happen <@task: __main__.add> >>> add.__evaluated__() True
應(yīng)用的Finalization指顯式地調(diào)用app.finalize()方法或隱式地訪問(wèn)app.tasks屬性。
finalized應(yīng)用將會(huì):
復(fù)制必須在應(yīng)用間共享的task。task默認(rèn)是共享的,但如果禁用了task裝飾器的shared屬性,將屬于應(yīng)用私有。
評(píng)估所有待處理的task裝飾器
確保所有task綁定到當(dāng)前應(yīng)用。將task綁定到某個(gè)應(yīng)用,以便可以從配置中讀取默認(rèn)值。
Breaking the chain雖然可以依賴于當(dāng)前應(yīng)用,但最佳實(shí)踐是將應(yīng)用實(shí)例傳遞給任何需要它的對(duì)象,這個(gè)行為可以稱為app chain。
# 依賴于當(dāng)前應(yīng)用(bad) from celery import current_app class Scheduler(object): def run(self): app = current_app
# 傳遞應(yīng)用實(shí)例(good) class Scheduler(object): def __init__(self, app): self.app = app
在開(kāi)發(fā)模式設(shè)置CELERY_TRACE_APP環(huán)境變量,可以在應(yīng)用鏈斷開(kāi)時(shí)拋出異常:
$ CELERY_TRACE_APP=1 celery worker -l infoAbstract Tasks
使用task()裝飾器創(chuàng)建的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)
如果要重寫(xiě)__call__()方法,記得調(diào)用super。這樣在task直接調(diào)用時(shí)會(huì)執(zhí)行基類的默認(rèn)事件。
Task基類是特殊的,因?yàn)樗⑽唇壎ǖ饺魏翁囟ǖ膽?yīng)用。一旦task綁定到應(yīng)用,它將讀取配置以設(shè)置默認(rèn)值等。
通過(guò)base參數(shù)指定基類
@app.task(base=DebugTask) def add(x, y): return x + y
通過(guò)app.Task屬性指定基類
>>> from celery import Celery, Task >>> app = Celery() >>> class MyBaseTask(Task): ... queue = "hipri" >>> app.Task = MyBaseTask >>> app.Task>>> @app.task ... def add(x, y): ... return x + y >>> add <@task: __main__.add> >>> add.__class__.mro() [ >, , , ]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/43221.html
摘要:所以這就現(xiàn)實(shí)了在中使用的應(yīng)用上下文。要引入請(qǐng)求上下文,需要考慮這兩個(gè)問(wèn)題如何在中產(chǎn)生請(qǐng)求上下文。中有和可以產(chǎn)生請(qǐng)求上下文。具體的思路還是在中重載類,通過(guò),在的上下文環(huán)境下執(zhí)行。將他們傳入,生成偽造的請(qǐng)求上下文可以覆蓋大多數(shù)的使用情況。 其實(shí)我只是想把郵件發(fā)送這個(gè)動(dòng)作移到Celery中執(zhí)行。既然用到了Celery,那么每次發(fā)郵件都單獨(dú)開(kāi)一個(gè)線程似乎有點(diǎn)多余,異步任務(wù)還是交給Celery吧...
摘要:使用異步框架,例如等等,裝飾異步任務(wù)。它是一個(gè)專注于實(shí)時(shí)處理的任務(wù)隊(duì)列,同時(shí)也支持任務(wù)調(diào)度。不存儲(chǔ)任務(wù)狀態(tài)。標(biāo)識(shí)要使用的默認(rèn)序列化方法的字符串。指定該任務(wù)的結(jié)果存儲(chǔ)后端用于此任務(wù)。 概述: ????????我們考慮一個(gè)場(chǎng)景,公司有一個(gè)需求,現(xiàn)在需要做一套web系統(tǒng),而這套系統(tǒng)某些功能需要使用...
摘要:中常用的幾個(gè)框架有等,今天來(lái)總結(jié)一下和的不同。本文使用的環(huán)境是。文件可以加載路由信息和項(xiàng)目配置信息,文件負(fù)責(zé)啟動(dòng)項(xiàng)目。以上就簡(jiǎn)單的比較了和幾個(gè)方面的不同,它們各有優(yōu)缺點(diǎn),實(shí)際工作中可以根據(jù)不同的需求選擇不同的框架進(jìn)行開(kāi)發(fā)。 python中常用的幾個(gè)web框架有django, tornado, flask等,今天來(lái)總結(jié)一下django和tornado的不同。工作中django和torna...
摘要:基于網(wǎng),分享項(xiàng)目的組網(wǎng)架構(gòu)和部署。項(xiàng)目組網(wǎng)架構(gòu)架構(gòu)說(shuō)明流項(xiàng)目訪問(wèn)分為兩個(gè)流,通過(guò)分兩個(gè)端口暴露給外部使用數(shù)據(jù)流用戶訪問(wèn)網(wǎng)站。通過(guò)進(jìn)行配置,使用作為異步隊(duì)列來(lái)存儲(chǔ)任務(wù),并將處理結(jié)果存儲(chǔ)在中。 基于Raindrop網(wǎng),分享項(xiàng)目的組網(wǎng)架構(gòu)和部署。 項(xiàng)目組網(wǎng)架構(gòu) showImg(https://cloud.githubusercontent.com/assets/7239657/1015704...
摘要:主要是為了實(shí)現(xiàn)系統(tǒng)之間的雙向解耦而實(shí)現(xiàn)的。問(wèn)題及優(yōu)化隊(duì)列過(guò)長(zhǎng)問(wèn)題使用上述方案的異步非阻塞可能會(huì)依賴于的任務(wù)隊(duì)列長(zhǎng)度,若隊(duì)列中的任務(wù)過(guò)多,則可能導(dǎo)致長(zhǎng)時(shí)間等待,降低效率。 Tornado和Celery介紹 1.Tornado Tornado是一個(gè)用python編寫(xiě)的一個(gè)強(qiáng)大的、可擴(kuò)展的異步HTTP服務(wù)器,同時(shí)也是一個(gè)web開(kāi)發(fā)框架。tornado是一個(gè)非阻塞式web服務(wù)器,其速度相當(dāng)快。...
閱讀 3555·2019-08-30 15:53
閱讀 3464·2019-08-29 16:54
閱讀 2254·2019-08-29 16:41
閱讀 2530·2019-08-23 16:10
閱讀 3436·2019-08-23 15:04
閱讀 1433·2019-08-23 13:58
閱讀 418·2019-08-23 11:40
閱讀 2512·2019-08-23 10:26