如何将带参数的类__exit__方法添加到Flask的teardown_appcontext中?
解决Flask中添加带参数的__exit__方法到teardown_appcontext的问题
你遇到的错误原因很直接:display.__exit__(None, None, None)是直接执行了这个方法,它的返回值是None,而app.teardown_appcontext()需要接收一个可调用对象(函数或方法),不是执行后的结果,所以才会报TypeError: 'NoneType' object is not callable。
下面是几种可行的解决方法:
方法1:用lambda包装__exit__方法
Flask的teardown_appcontext触发时,会自动传入三个异常相关参数(exc_type, exc_val, traceback),你可以用lambda接收这些参数,再传递给__exit__:
def init_app(): app = Flask(__name__) database.init_app(app) display = Display(mode='s') # 用lambda包装,传递teardown的参数给__exit__ app.teardown_appcontext(lambda exc_type, exc_val, traceback: display.__exit__(exc_type, exc_val, traceback)) with app.app_context(): from . import routes database.init_database() display.__enter__() return app
方法2:写一个显式的包装函数
如果觉得lambda不够直观,可以单独写一个包装函数,把display作为闭包变量:
def init_app(): app = Flask(__name__) database.init_app(app) display = Display(mode='s') # 定义包装函数 def teardown_display(exc_type, exc_val, traceback): display.__exit__(exc_type, exc_val, traceback) app.teardown_appcontext(teardown_display) with app.app_context(): from . import routes database.init_database() display.__enter__() return app
额外说明
因为你是手动调用了display.__enter__(),所以在app上下文销毁时手动触发__exit__是合理的。如果Display类是标准的上下文管理器,也可以考虑在app.app_context()的with块内嵌套display的with语句,但这取决于你的业务逻辑是否允许。
内容的提问来源于stack exchange,提问作者TJF
相关产品推荐
相关产品推荐

