如何轻松处理python中的动态装饰?

时间:2014-05-02 16:27:21

标签: python flask decorator python-decorators

假设我得到以下设置(简化):

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_connectOnetest_ConnectTwo移动到单独的模块中。我正在考虑为每个模块创建两个类,并使函数静态如下:

class ModuleOne (object):

    @staticmethod
    @socketio.on('connect', namespace='/namespaceOne')
    def test_One():
        print('new connection')

但有了这个,我遇到了麻烦。我现在必须以某种方式将socketio对象放入类中(例如,通过简单的setter与静态变量的组合)。但我想在我可以设置任何变量之前,在其他地方导入模块socketio.on()时,注释ModuleOne将会触发。

我该如何解决这种情况? (我对解决方案也持开放态度。但

1 个答案:

答案 0 :(得分:4)

您有两种选择:

  1. 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文档的Larger Application章节;特别是循环进口部分。

  2. 手动应用@socketio.on()装饰器&#39 ;; @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)