【发布时间】:2018-03-22 08:51:38
【问题描述】:
基本上,我试图在单独的线程中的服务器端生成事件。我有一个应该发出事件的celery.task,但它的代码永远不会执行。
import json
import time
from celery import Celery
from flask import Flask
from flask import jsonify
from flask import render_template
from flask import request
from flask_socketio import SocketIO
broker_url = "redis://localhost:6379/1"
celery = Celery(broker=broker_url)
app = Flask(__name__)
socketio = SocketIO(app, message_queue=broker_url)
@celery.task
def countdown(n):
print("countdown", n)
for i in range(n+1):
time.sleep(1)
socketio.emit(
"countdown",
{"remaining": n - i},
namespace="/test/"
)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/start_countdown/", methods=["POST"])
def start_countdown():
data = json.loads(request.data.decode())
countdown.delay([int(data["time"])])
return jsonify(time_to_wait=data["time"])
if __name__ == '__main__':
socketio.run(debug=True)
视图响应正常,但任务无声,我无法理解,为什么?
UPD
我重新排列了我的代码,例如 here。文件夹结构完全一样,文件也一样。在app/main 文件夹中,我有额外的tasks.py 文件。
import time
from celery import Celery
from flask_socketio import emit
from app import socketio
from config import broker_url
celery = Celery(broker=broker_url)
@celery.task
def countdown(n):
print(n)
for i in range(n+1):
time.sleep(1)
print("Socket", socketio)
print("Server", socketio.server)
socketio.emit(
"countdown",
{"remaining": n - i},
namespace="/test/"
)
我使用 celery -A app.main.tasks worker 命令启动 celery worker。当countdown 任务的代码被执行时,它会因为这个异常而失败:
[2017-10-12 19:04:07,797: WARNING/ForkPoolWorker-1] 13
[2017-10-12 19:04:08,799: WARNING/ForkPoolWorker-1] <flask_socketio.SocketIO object at 0x7f07d2a0fc50>
[2017-10-12 19:04:08,803: ERROR/ForkPoolWorker-1] Task app.main.tasks.countdown[68ae2e43-6ab7-4d52-8b3a-a9aaff46c489] raised unexpected: AttributeError("'NoneType' object has no attribute 'emit'",)
Traceback (most recent call last):
File "/path/to/venv/lib/python3.4/site-packages/celery/app/trace.py", line 374, in trace_task
R = retval = fun(*args, **kwargs)
File "/path/to/venv/lib/python3.4/site-packages/celery/app/trace.py", line 629, in __protected_call__
return self.run(*args, **kwargs)
File "/path/to/tasks.py", line 24, in countdown
namespace="/test/"
File "/path/to/venv/lib/python3.4/site-packages/flask_socketio/__init__.py", line 357, in emit
self.server.emit(event, *args, namespace=namespace, room=room,
AttributeError: 'NoneType' object has no attribute 'emit'
我的任务中的socketio.server 出于某种原因是None,而在app/main/events.py 文件中它是适当的对象。看起来在我的任务中socketio 对象没有完全初始化,可能是因为在 celery 进程中执行流程不同,但我不知道如何修复它。
【问题讨论】:
-
你是如何从客户端连接到这个应用程序的?
-
@Miguel,这里是 index.html 和 magic.js gist.github.com/montreal91/8a9ba9033df1469ccd51e1c2e7a3ac9f。如果需要,我可以将它们添加到帖子中。
start_countdown被调用,但后台任务没有启动。 -
除了您的主服务器之外,是否至少运行一个 Celery 工作进程?
-
现在,是的。
-
那么任务是否正在运行?您可以将日志记录添加到 Celery worker 以查看它是否启动了任务。
标签: python flask celery flask-socketio