如果 socketIO 实例是 class 成员变量,如何用 flask-socketio 修饰 class 函数?

How to decorate class functions with flask-socketio if the socketIO instance is a class member variable?

我正在尝试为带有 socketio 的烧瓶应用程序创建一个 hello world 示例,它被包装到 class 中。

我想将整个应用程序包装成一个 class,可以嵌入到其他应用程序中。为此,我在 class 的构造函数中创建了 Flask 应用程序,并且还创建了 SocketIO 实例作为成员。 问题是我得到一个 NameError 异常告诉我 'socketio' 没有定义。

我已尝试改编来自 flask-socketio 教程的最小工作示例 (https://flask-socketio.readthedocs.io/en/latest/)

这是我尝试开始工作的示例代码:

from flask import Flask
from flask_socketio import SocketIO, emit

class ApplicationExample:

    def __init__(self):
        self.app = Flask(__name__)
        self.socketio = SocketIO(self.app)

    @socketio.on('ping')
    def pongResponse(self, message):
        emit('pong')

    def run(self):
        self.socketio.run(service.app, host='0.0.0.0')

if __name__ == '__main__':
    service = ApplicationExample()
    service.run()

我想将 pongResponse 函数绑定到 class 中的 socketio 实例。如何在将 SocketIO class 作为成员的同时装饰函数?

由于装饰一个函数只是调用装饰器并将装饰后的函数作为第一个参数传递,您可以这样写:

def __init__(self):
    ... 
    self.pongResponse = self.socketio.on('ping')(self._pongResponse)

def _pongResponse(self, message):
    ...

_ 开头的方法表示它不是 class 的 public API 的一部分(因此这只是一个约定)。另请注意,在 python 中,您应该使用 snake_case 而不是 camelCase 来命名您的函数和变量,尽管这也只是一个约定。

根据文档,您可以使用下面的而不是装饰器

def my_function_handler(data):
    pass

socketio.on_event('my event', my_function_handler, namespace='/test')

这会变成

from flask import Flask
from flask_socketio import SocketIO, emit

class ApplicationExample:
    def __init__(self):
        self.app = Flask(__name__)
        self.socketio = SocketIO(self.app)
        self.socketio.on_event('ping', self.pongResponse, namespace='/test')

    def pongResponse(self, message):
        emit('pong')

    def run(self):
        self.socketio.run(service.app, host='0.0.0.0')