【问题标题】:working outside of application context - Flask在应用程序上下文之外工作 - Flask
【发布时间】:2016-03-11 10:17:28
【问题描述】:
def get_db(self,dbfile):
    if hasattr(g, 'sqlite_db'): self.close_db(g.sqlite_db)
    try:
        g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))
    except sqlite3.OperationalError as e:
        raise e

    return g.sqlite_db

您好,这段代码位于 DB 类中,我得到的错误是

RuntimeError:在应用程序上下文之外工作

错误发生在这一行

g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))

我认为问题出在g上,它是这样导入的from flask import g

如何修复此错误? 谢谢。

【问题讨论】:

    标签: python flask


    【解决方案1】:

    来自flask/globals.py中的Flask源代码:

    _app_ctx_err_msg = '''\
    Working outside of application context.
    
    This typically means that you attempted to use functionality that needed
    to interface with the current application object in a way.  To solve
    this set up an application context with app.app_context().  See the
    documentation for more information.\
    '''
    

    按照文档,您可以看到您需要将flask.current_app 指向您的应用程序,而目前没有。

    您可能在 Flask 初始化之前调用了您的 DB 函数。我的猜测是您的 app 对象尚未使用 Flask 构造函数创建。

    【讨论】:

      【解决方案2】:

      也许您需要在应用程序上下文中调用您的函数:

      with app.app_context():
        # call your method here
      

      【讨论】:

        【解决方案3】:

        错误:这通常意味着您尝试使用需要的功能 以某种方式与当前应用程序对象交互。解决 这使用 app.app_context() 设置了一个应用程序上下文。见 文档以获取更多信息。

        【讨论】:

        • 投反对票。除了错误发生时用户已经看到的内容之外,此答案没有提供任何内容。
        【解决方案4】:

        创建应用时,请使用:

        app.app_context().push()
        

        例如这样:

        from yourapp import create_app
        
        app = create_app()
        
        app.app_context().push()
        

        for further information

        【讨论】:

          【解决方案5】:

          扩展@VadimK 的答案。如果您想阻止您的代码在app_context 之外执行,您可以使用flask.has_app_context() 查看代码当前是否在app context 内:

          另见:flask.has_request_context()

          【讨论】:

            【解决方案6】:

            我在进行单元测试时遇到了同样的问题。

            将以下函数添加到我的测试类解决了我的问题:

            @classmethod
            def setUpClass(self):
                self.app = create_app("testing")
                self.client = self.app.test_client()
            

            【讨论】:

              【解决方案7】:

              其他用户已指出如何解决眼前的问题,但您可以考虑修改创建数据库连接的方式来解决此问题。

              您可以在每次请求之前在控制器中创建连接,而不是在 DB 类中实例化数据库连接。然后使用 teardown_request 装饰器关闭连接。

              然后,当在路由中时,您可以将连接传递给 DB 类,作为实例化新 DB 对象的一部分。

              这将确保您永远不会创建数据库连接,除非您需要。它会阻止您在应用上下文之外访问 Flask 全局变量。

              @app.before_request
              def before_request():
                  try:
                      g.sqlite_db = self.connect_db('{}/{}'.format(app.root_path, dbfile))
                  except sqlite3.OperationalError as e:
                      raise e
              
              @app.teardown_request
              def teardown_request(e):
                  if hasattr(g, 'sqlite_db'): self.close_db(g.sqlite_db)
              
              @app.route('/someroute', methods=["GET"]:
              def someroute():
                  db_obj = DB(g.sqlite_db)
                  .
                  .
                  .
              

              【讨论】:

                猜你喜欢
                • 2016-07-12
                • 2020-10-13
                • 1970-01-01
                • 2022-10-06
                • 2021-09-17
                • 1970-01-01
                • 1970-01-01
                • 2015-10-05
                • 2018-11-08
                相关资源
                最近更新 更多