Celery 与 Flask 大型程序结构的结合


:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; max-width: 100%; height: auto !important; margin: 2px 0; } table { border-collapse: collapse; border: 1px solid #bbbbbb; } td, th { padding: 4px 8px; border-collapse: collapse; border: 1px solid #bbbbbb; } @media only screen and (-webkit-max-device-width: 1024px), only screen and (-o-max-device-width: 1024px), only screen and (max-device-width: 1024px), only screen and (-webkit-min-device-pixel-ratio: 3), only screen and (-o-min-device-pixel-ratio: 3), only screen and (min-device-pixel-ratio: 3) { html, body { font-size: 17px; } body { line-height: 1.7; padding: 0.75rem 0.9375rem; color: #353c47; } h1 { font-size: 2.125rem; } h2 { font-size: 1.875rem; } h3 { font-size: 1.625rem; } h4 { font-size: 1.375rem; } h5 { font-size: 1.125rem; } h6 { color: inherit; } ul, ol { padding-left: 2.5rem; } blockquote { padding: 0 0.9375rem; } }
-->

div{font-size:15px;}.wiz-table-tools .wiz-table-menu-item.active .wiz-table-menu-sub {display: block}.wiz-table-tools .wiz-table-menu-sub:before, .wiz-table-tools .wiz-table-menu-sub:after {position: absolute;content: " ";border-style: solid;border-color: transparent;border-bottom-color: #cccccc;left: 22px;margin-left: -14px;top: -8px;border-width: 0 8px 8px 8px;z-index:10;}.wiz-table-tools .wiz-table-menu-sub:after {border-bottom-color: #ffffff;top: -7px;}.wiz-table-tools .wiz-table-menu-sub-item {padding: 4px 12px;font-size: 14px;}.wiz-table-tools .wiz-table-menu-sub-item.split {border-top: 1px solid #E0E0E0;}.wiz-table-tools .wiz-table-menu-sub-item:hover {background-color: #ececec;}.wiz-table-tools .wiz-table-menu-sub-item.disabled {color: #bbbbbb;cursor: default;}.wiz-table-tools .wiz-table-menu-sub-item.disabled:hover {background-color: transparent;}.wiz-table-tools .wiz-table-menu-item.wiz-table-cell-bg:hover .wiz-table-color-pad {display: block;}.wiz-table-tools .wiz-table-color-pad {display: none;padding: 10px;box-sizing: border-box;width: 85px;height: 88px;background-color: #fff;cursor: default;}.wiz-table-tools .wiz-table-color-pad > div{font-size:15px;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item {display: inline-block;width: 15px;height: 15px;margin-right: 9px;position: relative;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item i.pad-demo {position: absolute;top:3px;left:0;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item .icon-oblique_line{color: #cc0000;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item:last-child {margin-right: 0;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item.active i.editor-icon.icon-box {color: #448aff;}.wiz-table-tools .wiz-table-cell-align {display: none;padding: 10px;box-sizing: border-box;width: 85px;height: 65px;background-color: #fff;cursor: default;}.wiz-table-tools .wiz-table-cell-align .wiz-table-cell-align-item {display: inline-block;width: 15px;height: 15px;margin-right: 9px;position: relative;}.wiz-table-tools .wiz-table-cell-align .wiz-table-cell-align-item:last-child {margin-right:0}.wiz-table-tools .wiz-table-cell-align .wiz-table-cell-align-item i.valign{position: absolute;top:3px;left:0;color: #d2d2d2;}.wiz-table-tools .wiz-table-cell-align-item.active i.editor-icon.valign {color: #a1c4ff;}.wiz-table-tools .wiz-table-cell-align-item.active i.editor-icon.icon-box,.wiz-table-tools .wiz-table-cell-align-item.active i.editor-icon.align {color: #448aff;}.wiz-table-tools .wiz-table-color-pad .wiz-table-color-pad-item:last-child,.wiz-table-tools .wiz-table-cell-align .wiz-table-cell-align-item:last-child {margin-right: 0;}th.wiz-selected-cell-multi, td.wiz-selected-cell-multi {background: rgba(0,102,255,.05);}th:before,td:before,#wiz-table-col-line:before,#wiz-table-range-border_start_right:before,#wiz-table-range-border_range_right:before{content: " ";position: absolute;top: 0;bottom: 0;right: -5px;width: 9px;cursor: col-resize;background: transparent;z-index:100;}th:after,td:after,#wiz-table-row-line:before,#wiz-table-range-border_start_bottom:before,#wiz-table-range-border_range_bottom:before{content: " ";position: absolute;left: 0;right: 0;bottom: -5px;height: 9px;cursor: row-resize;background: transparent;z-index:100;}.wiz-table-container {}.wiz-table-body {position:relative;padding:0 0 10px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;}.wiz-table-body table {margin:0;outline:none;}td,th {height:28px;word-break:break-all;box-sizing:border-box;outline:none;}body pre.prettyprint {padding:0;}body pre.prettyprint code {white-space: pre;}body pre.prettyprint.linenums {box-shadow:none; overflow: auto;-webkit-overflow-scrolling: touch;}body pre.prettyprint.linenums ol.linenums {box-shadow: 40px 0 0 #FBFBFC inset, 41px 0 0 #ECECF0 inset; padding: 10px 10px 10px 40px !important;}
-->

Celery 与 Flask 大型程序结构结合的关键:

使 Celery 与 Flask 结合的关键在于非 Web Runtime 中调取上下文。
因为当 Flask App 在作为 WSGI Application 运行时,会在每个请求进入的时候将请求上下文推入 _request_ctx_stack 中。推入请求上下文的同时,将检查应用上下文堆栈 _app_ctx_stack 是否为空,若空则隐式地推入一个 应用上下文。最终,在请求线程退出前,应用上下文将从其 Flask._app_ctx_stack 的栈中里弹出
Celery 作为任务调度模块,其任务执行单元(worker)运行时,将处于非 Web Runtime 的状态,而此时应用上下文堆栈 Flask._app_ctx_stack 为空,因此调取上下文将引发"RunTimeError"的报错。
Flask 大型程序结构下,采用工厂函数(create_app)创建 Flask App,因此同样采用工厂函数的形式创建 Celery App,其工厂函数如下:
from celery import Celery
                                    
def make_celery(App):
    CeleryInst = Celery(App.import_name, backend = App.config['CELERY_RESULT_BACKEND'], broker = App.config['CELERY_BROKER_URL'])
    CeleryInst.conf.update(App.config)
    TaskBase = CeleryInst.Task
    class ContextTask(TaskBase):
        """Will be execute when create the instance object of ContextTasks."""
        # Will context(Flask's Extends) of app object(Producer Sit)
        # be included in celery object(Consumer Site).
        abstract = True
        def __call__(self, *args, **kwargs):
            with App.app_context():
                return TaskBase.__call__(self, *args, **kwargs)
    # Include the app_context into celery.Task.
    # Let other Flask extensions can be normal calls.
    CeleryInst.Task = ContextTask
    return CeleryInst
 
 
注意:此方式创建 Celery 对象时,将会把用于初始化的 Flask App 的上下文信息包含至 Celery 对象中。基于此,Flask 扩展在调用 Celery 任务时,采用最普通的方式,而不需额外考虑上下文问题。
 
Celery 与 Flask 大型程序结构结合的实例:
Flask 大型程序结构如下。
|-flasky
   |-app/
       |-templates/
       |-static/
       |-main/
           |-__init__.py
           |-errors.py
           |-forms.py
           |-views.py
       |-__init__.py
       |-mail/
           |-templates/
           |-__init__.py
           |-mail.py
   |-migrations/
   |-tests/
       |-__init__.py
       |-test*.py
|-venv/
|-requirements.txt
|-config.py
|-manage.py
注意:与原 Flask 大型程序结构作出如下修改以及强调
(1).Flask App 及 Celery App 创建于 /flasky/app/__init__.py 中。
(2).manage.py 中通过 import 方式引入 Flask App,并在该文件中启用 WSGI。
(3).在其他需要调用 Flask App 的地方,采用 current_app._get_current_object() 实现。
 
 
 
 
上一篇:【Echarts】图表用echarts【待完善】


下一篇:[codevs2152]滑雪