如何轻松处理Python中的动态装饰器?
假设我有以下的设置(简化版):
from flask import Flask
from flask.ext.socketio import SocketIO, emit, send
app = Flask(__name__)
socketio = SocketIO(app)
@socketio.on('connect', namespace='/namespaceOne')
def test_connectOne():
print('new connection')
@socketio.on('connect', namespace='/namespaceTwo')
def test_connectTwo():
print('new connection')
if __name__ == '__main__':
socketio.run(app)
现在我想把两个函数 test_connectOne
和 test_ConnectTwo
移到不同的模块里。我在考虑为每个模块创建两个类,并把这些函数设为静态的,像这样:
class ModuleOne (object):
@staticmethod
@socketio.on('connect', namespace='/namespaceOne')
def test_One():
print('new connection')
但这样做我遇到了一些麻烦。我需要想办法把 socketio 对象放进类里(比如通过一个简单的设置方法和一个静态变量结合起来)。不过我想,注解 socketio.on()
会在模块 ModuleOne
被其他地方导入时就触发,而那时我还没来得及设置任何变量。
我该怎么解决这个问题呢?(我也欢迎一些完全不同的解决方案。)
1 个回答
4
你有两个选择:
把
socketio
对象导入到你放置视图的单独模块中。只要你在创建socketio
对象后再导入这个模块,事情就能正常运作。所以在你的main
模块里,你可以这样写:from flask import Flask from flask.ext.socketio import SocketIO, emit, send app = Flask(__name__) socketio = SocketIO(app) import socket_views if __name__ == '__main__': socketio.run(app)
而在
socket_views.py
里,你可以这样写:from main import socketio @socketio.on('connect', namespace='/namespaceOne') def test_connectOne(): print('new connection') @socketio.on('connect', namespace='/namespaceTwo') def test_connectTwo(): print('new connection')
可以参考 Flask 文档中的 大型应用章节,特别是循环导入的部分。
手动使用
@socketio.on()
装饰器;@expression
这种写法只是让你更方便地把一个可调用的东西应用到一个函数上。因为@socketio.on()
装饰器只是用来“注册”的,所以你可以把你的视图写成普通的、不带装饰器的函数,然后在导入后用下面的方式注册它们:from socket_views import test_connectOne, test_connectTwo socketio.on('connect', namespace='/namespaceOne')(test_connectOne) socketio.on('connect', namespace='/namespaceTwo')(test_connectTwo)