- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我并没有尝试在 View 函数中使用 celery.current_app
,但是我有一个挂接到 after_task_publish
信号的函数,该信号使用它来更新状态发布任务后,它在 Flask View 函数之外工作并正确更新状态,但是当我从 View 函数内部发送任务时,任务状态不会更新,我检查了一下,问题是 current_app.backend
是 DisabledBackend
的一个实例,它是默认的,而不是我正在使用的 RedisBackend
的一个实例。
发生这种情况是因为在 Flask View 函数中,当前 Celery 实例 celery.current_app
的代理指的是在没有当前 Celery 实例时创建的默认实例。
我尝试重现正在发生的事情,这是一个测试脚本:
from __future__ import absolute_import, print_function, unicode_literals
from flask import Flask, request
from celery import Celery, current_app
from celery.signals import after_task_publish
# internal module for debugging purposes
from celery._state import default_app, _tls
# the flask application
flask_app = Flask(__name__)
# the celery application
celery_app = Celery('tasks', broker='amqp://', backend='redis://')
# debugging info
debug = """
[{location}]
celery_app = {celery_app}
current_app = {current_app}
add.app = {add_app}
default_app = {default_app}
_tls.current_app = {tls_current_app}
"""
print(debug.format(
location = 'OUTSIDE VIEW',
celery_app = celery_app,
current_app = current_app,
add_app = add.app,
default_app = default_app,
tls_current_app = _tls.current_app
))
# fired after a task is published
@after_task_publish.connect
def after_publish(sender=None, body=None, **kwargs):
print(debug.format(
location = 'INSIDE SIGNAL FUNCTION',
celery_app = celery_app,
current_app = current_app,
add_app = add.app,
default_app = default_app,
tls_current_app = _tls.current_app
))
# a simple task for testing
@celery_app.task(name='add')
def add(a, b):
return a + b
@flask_app.route('/add')
def add_view():
print(debug.format(
location = 'INSIDE VIEW',
celery_app = celery_app,
current_app = current_app,
add_app = add.app,
default_app = default_app,
tls_current_app = _tls.current_app
))
a = request.args.get('a')
b = request.args.get('b')
task = add.delay(a, b)
return task.task_id
if __name__ == '__main__':
flask_app.run(debug=True)
这是输出:
[OUTSIDE VIEW]
celery_app = <Celery tasks:0xb69ede4c>
current_app = <Celery tasks:0xb69ede4c>
add.app = <Celery tasks:0xb69ede4c>
default_app = None
_tls.current_app = <Celery tasks:0xb69ede4c>
[INSIDE VIEW]
celery_app = <Celery tasks:0xb69ede4c>
current_app = <Celery default:0xb6b0546c>
add.app = <Celery tasks:0xb69ede4c>
default_app = None
_tls.current_app = None # making current_app fallback to the default instance
[INSIDE SIGNAL FUNCTION]
celery_app = <Celery tasks:0xb69ede4c>
current_app = <Celery default:0xb6a174ec>
add.app = <Celery tasks:0xb69ede4c>
default_app = None
_tls.current_app = None
因为 _tls.current_app
在 View 中是 None,这就是 celery.current_app
引用默认实例的原因,来自 celery._state._get_current_app
:
return _tls.current_app or default_app
_tls
是 celery._state._TLS
的实例:
class _TLS(threading.local):
#: Apps with the :attr:`~celery.app.base.BaseApp.set_as_current` attribute
#: sets this, so it will always contain the last instantiated app,
#: and is the default app returned by :func:`app_or_default`.
current_app = None
问题与线程相关吗?这可能是一个错误吗?还是这是预期的行为?
请注意,我可以在我的钩子(Hook)函数中使用实际的 celery 实例,一切都会正常工作,但我担心在其他地方使用的 celery.current_app
会破坏我的代码。
最佳答案
我在未启用调试的情况下运行 Flask 应用程序时发现了问题,并且它没有任何问题地工作,当 debug
为 True
时,使用重新加载程序运行应用程序另一个线程,这发生在 werkzeug._reloader.run_with_reloader
函数中。
并且取决于 Python docs关于 threading.local
类,它被子类化以存储当前应用程序实例:
A class that represents thread-local data. Thread-local data are data whose values are thread specific.
The instance’s values will be different for separate threads.
所以这意味着 celery._state._tls.current_app
不在线程之间共享,我们必须手动将 celery 实例设置为当前应用程序,例如在 View 函数中:
celery_app.set_current()
关于python - 为什么 `celery.current_app` 引用 Flask View 函数中的默认实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26527214/
我正在尝试从蓝图(我将在模板中使用的函数)在 Jinja 环境中添加一个函数。 主.py app = Flask(__name__) app.register_blueprint(heysyni) M
最近,我开始使用 Flask 构建应用程序。它非常易于使用,但功能强大且使用起来很有趣。不幸的是,我在理解应用程序上下文的工作方式时遇到了问题。我知道 current_app、app_context
current_app 和 g 都是应用程序上下文变量,因此它们会随着每个请求加载和卸载,因此存储在它们上的任何数据都只能在同一个请求中使用. 我能看到的唯一区别是 g 在每个请求的开头都是空的,而
我正在使用 current_app.logger,当我尝试登录线程内部时,它显示“在应用程序上下文之外工作”。如何记录来自线程中运行的方法的消息? def background(): curr
这个问题在这里已经有了答案: Are global variables thread-safe in Flask? How do I share data between requests? (4 个
我尝试为 Flask 创建两个装饰器来装饰一个简单的函数。两个装饰器都需要访问 current_app 上的相同字段/属性。装饰函数也需要访问相同的属性。但我想测试这个字段是否已经存在并在任一装饰器中
我在我的 Flask 应用程序上看到了一个相当奇怪的行为:嵌套的 app_contexts 没有在我的测试套件上正常工作,因此 current_app localproxy 没有指向正确的应用程序。它
我正在编写可重复使用的应用程序。我想多次部署它。 这是 urls.py: urlpatterns = patterns('', (r'^carphotos/', include('webui.phot
我已经设置了 Sphinx 来记录我的 Flask 项目,但是,我遇到了这个错误: [$]>>> make html sphinx-build -b html -d build/doctrees -
我在使用 current_app.send_task 时遇到 Celery 队列路由问题 我有两个 worker (每个队列一个) python manage.py celery worker -E
我不敢相信这会这么难。我在网上评分试图找到解决方案,但仍然无法访问我的 Flask 应用程序的 root_path。更糟糕的是,它在一个文件中有效,而在另一个文件中却无效。这是我尝试过的: from
我想对以下功能进行单元测试: from flask import current_app def fuu(): current_app.logger.info('hello world')
我在运行 CentOS 7 的服务器上使用 Django 1.11 (Python/2.7.5) + Apache/2.4.6 + mod_wsgi/3.4 部署了一个应用程序。 页面工作正常,但登录
我并没有尝试在 View 函数中使用 celery.current_app,但是我有一个挂接到 after_task_publish 信号的函数,该信号使用它来更新状态发布任务后,它在 Flask V
好的,我已经尝试了我和谷歌所能想到的一切。我正在尝试在我的 Macbook Pro OSX 10.8.4 上的 virtualenv 下运行 django-celery。我在激活 virtualenv
我刚刚通过 Gitlab 将我的应用程序上传到生产服务器 (Centos7) 并进行了迁移,一切正常,这里的问题是,一旦我想通过浏览器访问,我就会在日志中收到此错误: File "/usr/lib/p
我刚刚将 Django 从 1.9 升级到 1.10。我在测试环境中运行 1.10 并解决了所有升级问题以确保一切正常。 但是,当我在我的实时网站上执行此操作并加载主页时,我收到以下错误 环境: Re
我的应用程序中有一些已弃用的自定义端点,以支持从旧 API 迁移到 Eve。我的自定义端点之一实现了一个端点,用于更新 MongoDB 数据库中的文档。与这些文档关联的集合具有在 settings.p
是的,我知道有很多关于与这个值错误相关的堆栈溢出的类似问题,我尝试了他们的所有解决方案,但由于我是 Django 和 python 的新手,我无法解决这个问题。 我有一个名为 my_backend 的
我是一名优秀的程序员,十分优秀!