Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x Flask SocketIO-如何从子进程发出事件_Python 3.x_Flask_Socket.io_Flask Socketio - Fatal编程技术网

Python 3.x Flask SocketIO-如何从子进程发出事件

Python 3.x Flask SocketIO-如何从子进程发出事件,python-3.x,flask,socket.io,flask-socketio,Python 3.x,Flask,Socket.io,Flask Socketio,我有一个Flask应用程序,它在某些rest调用时使用ProcessPoolExecutor运行几个模块 更新:添加redis作为消息队列(使用docker,redis作为redis的主机) 现在我添加了redis,它在从主应用程序发射时仍然可以工作。 下面是我正在运行的子进程中的一些代码: def __init__(self): self.executor = futures.ProcessPoolExecutor(max_workers=4) self.socketio =

我有一个Flask应用程序,它在某些rest调用时使用ProcessPoolExecutor运行几个模块

更新:添加redis作为消息队列(使用docker,redis作为redis的主机)

现在我添加了redis,它在从主应用程序发射时仍然可以工作。 下面是我正在运行的子进程中的一些代码:

def __init__(self):
    self.executor = futures.ProcessPoolExecutor(max_workers=4)
    self.socketio = SocketIO(async_mode='eventlet', message_queue='redis://redis')

    (...)
    future = self.executor.submit(process, params)
    future.add_done_callback(functools.partial(self.finished_callback, pid))
然后在该回调中,我调用
emit\u事件
方法:

def finished_callback(self, pid, future):
    pid.status = Status.DONE.value
    pid.finished_at = datetime.datetime.utcnow
    pid.save()

    self.socketio.emit('update_reports', 'done', namespace='/test')
从我的控制器从/向客户端获取和发送/发送消息工作正常,如果我从curl或postman调用/info,我的客户端也会收到消息-但是-当尝试从这个子流程回调中以相同的方式发送事件时,现在它会显示以下错误:

这主要是用于通知,比如当一个长过程完成时通知等等

INFO:socketio:向所有[/test]发送事件“更新报告”
错误:socketio:无法发布到redis。。。重试
错误:socketio:无法发布到redis。。。放弃

我做错了什么


谢谢

在设置Flask SocketIO扩展时,您需要遵循一些特定规则,以便外部进程可以发出消息,其中包括使用主进程和外部进程用来协调工作的消息队列。有关说明,请参阅文档的部分。

能否添加用于从子流程发出的代码?您还提到了
/info
路线,但您的示例中有
/test
。我假设这就是您从curl调用的路由?感谢您的回复,Miguel,在子流程中,我只是从它所在的主py文件导入
emit\u event
方法,并以与我在该
/test
调用中相同的方式使用它。是的,这就是我正在调用的url。结果是,从子进程中,事件/消息永远不会到达(控制台中没有错误)@Miguel我刚刚添加了一些代码,请告诉我您的想法谢谢您的回答。我刚刚试着从我的子进程运行那里写的东西,但是这是我在日志中得到的
无法发布到redis。。。重试,放弃
我刚刚用更多细节和代码更新了问题。看来您的子进程没有连接到Redis。您可以尝试编写一个简单的脚本来连接到消息队列并发出消息吗?如果这样做有效,那么您必须找出您的子进程中有什么影响到与redis的连接。子进程不需要使用eventlet,只有主进程才需要。您在子流程中所做的事情似乎与eventlet不兼容,所以最好不要在那里使用它。您可以通过在
SocketIO
类构造函数中传递
async\u mode='threading'
并删除所有monkey补丁来强制Socket.IO不使用eventlet。然后您可以单独启动子进程吗?我自己并没有真正和执行者合作过,我更喜欢把事情分开,自己启动每个服务。如果您正在寻找我见过的成功使用的替代方案,芹菜和RedisQueue都很好,但我坚持认为您必须确保这些工作进程不使用eventlet,因为您似乎正在使用eventlet不支持的函数。
def finished_callback(self, pid, future):
    pid.status = Status.DONE.value
    pid.finished_at = datetime.datetime.utcnow
    pid.save()

    self.socketio.emit('update_reports', 'done', namespace='/test')