Flask Socket.Io:导入后初始化的socketio的持久性

Posted

技术标签:

【中文标题】Flask Socket.Io:导入后初始化的socketio的持久性【英文标题】:Flask Socket.Io: Persistence of initialized socketio after import 【发布时间】:2018-02-10 00:47:56 【问题描述】:

所以我有以下 websocket 服务器 api:

//x.py
......
import y

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@socketio.on('connected', namespace='/getDefects')
def connected():
    y.set_client_sid(request.sid)
    y.set_socketio(socketio)


@socketio.on('disconnect', namespace='/getDefects')
def disconnect():
    print("Client disconnected")

def sendDefects(def, sid, socketio_input):
    socketio = socketio_input
    socketio.emit('defects', def, room=sid, namespace='/getDefects')


def processDefWithContext(text):
    with app.test_request_context():
        y.processDef(text)

@app.route('/Process', methods=['Post'])
def process():
    text = request.form.get('text') 
    thread1 = Thread(target = processDefWithContext, args = (text,))
    thread1.start()
    response = "Ok"
    return response

if __name__ == '__main__':
    socketio.run(app, host='127.0.0.1', port=8080)


//y.py
import x
....
clientSid = 0
socketIo = 0
def set_client(sid):
    clientSid = sid

def set_socketio(socket_in):
    socketIo = socket_in


processDef(text):
    ....
    def = ..
    x.sendDefects(def, clientSid, socketio)

所以基本上 x.py 包含一个处理输入和输出请求的 web api。 它使用发布请求 (process()) 获取一些数据,然后在新线程中触发对该数据的一些处理。处理在 y.py 中完成。处理完成后,需要使用来自 x.py 的 websocket 将新数据发送到前端 所以 x.py 导入 y.py 并且 y.py 导入 x.py。问题是当我们从 y.py 调用函数来从 x.py 发送数据 (sendDefects(..)) 时,socketio 不再初始化并且将无法发送它.

到目前为止我找到的解决方案(我不是经验丰富的 Python 程序员)是将 socketio 从 x.py 发送到 y.py (set_socketio()) 并返回然后使用它发送数据。

但这个解决方案似乎有点难看。你能推荐另一种方法吗?

【问题讨论】:

【参考方案1】:

这实际上是 Python 应用程序的主模块发生的奇怪事情的副作用。我假设您以以下方式启动您的应用程序:

python x.py

对吗?在这种情况下,您的x.py 模块被命名为__main__,而不是x。因此,您的应用程序的导入顺序最终会创建您的 x 模块的两个副本。这可能不是很清楚,所以让我描述一下您的应用中发生的情况:

python解释器导入x.py,由于是主模块,所以在模块列表中存储为__main____main__ 模块导入y,存储为yy 模块导入x。在这里,解释器确定 x 尚未导入(因为 x 的现有实例称为 __main__),因此它以该名称导入 x 的第二个副本。 所以当y 调用x 中的函数时,它正在调用具有未初始化socketio 变量的副本。 socketio 未初始化的原因是初始化被包装在 if __name__ == '__main__' 条件中,因此只会在第一个实例中运行。

那么你如何解决这个问题?在y.py 中,将import x 替换为:

import __main__ as x

这将确保您不会收到重复的 x

【讨论】:

嗨。好的,我明白了。感谢您的解决方案。我会试试看。

以上是关于Flask Socket.Io:导入后初始化的socketio的持久性的主要内容,如果未能解决你的问题,请参考以下文章

flask_socket.io _ 运行异步任务的问题

如何使用 Flask 和 Socket.io 加入和离开房间的简明示例?

Flask socket.IO 服务器上的 Node.js Socket.io 客户端

Socket.io 与 flask-socketio python。如何设置套接字保持活动/超时

网站后端_Flask-第三方库.利用Flask-Socketio扩展构建实时流应用?

python Flask-socket.io向特定客户端发出