【问题标题】:How to handle dynamic decorators in python easily?如何轻松处理python中的动态装饰器?
【发布时间】:2014-06-19 09:54:02
【问题描述】:

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

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 被导入到其他地方时触发,然后我才能设置任何变量。

我该如何解决这种情况? (我也愿意接受完全不同方向的解决方案。)

【问题讨论】:

  • 不,装饰器在用作方法装饰器时也会被视为全局变量;在定义 test_One() 方法时查找装饰器。我不会将您的函数放在一个类中,即使是作为静态方法。它根本没有额外的优势,只会使您的代码在这里复杂化。将视图放在实际单独的模块文件中。
  • 但是我怎样才能以干净的方式将 socketio 对象放入这些模块中呢?
  • 可以导入;在您的主模块中导入带有视图的模块之后定义了socketio 对象,然后带有视图的模块可以使用from mainmodule import socketio
  • 参见flask.readthedocs.org/en/latest/patterns/packages,关于循环进口的部分。
  • 嗯听起来还是很复杂/不是很漂亮。最后让一切保持原样对我来说似乎是迄今为止最干净的。有没有可能手动调用装饰器?例如。 socketio.on(test_One, 'connect', namespace='/namespaceOne');不幸的是,我找不到任何有关此的信息...

标签: python flask decorator python-decorators


【解决方案1】:

你有两个选择:

  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() 装饰器; @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)
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 2020-03-29
    相关资源
    最近更新 更多