V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
plko345
V2EX  ›  Python

flask 的 Working outside of application context 求助

  •  
  •   plko345 · 2020-12-19 12:20:41 +08:00 · 3165 次点击
    这是一个创建于 1217 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在类属性读 flask 的配置报错

    from flask import current_app
    
    class Foo(object):
        URL = current_app.config['EX_URL']
        ...
    
      File "/path/to/example.py", line 20, in Foo
        URL = current_app.config['EX_URL']
      File "/path/to/miniconda/envs/example/lib/python3.8/site-packages/werkzeug/local.py", line 347, in __getattr__
        return getattr(self._get_current_object(), name)
      File "/path/to/miniconda/envs/example/lib/python3.8/site-packages/werkzeug/local.py", line 306, in _get_current_object
        return self.__local()
      File "/path/to/miniconda/envs/example/lib/python3.8/site-packages/flask/globals.py", line 52, in _find_app
        raise RuntimeError(_app_ctx_err_msg)
    RuntimeError: Working outside of application context.
    
    This typically means that you attempted to use functionality that needed
    to interface with the current application object in some way. To solve
    this, set up an application context with app.app_context().  See the
    documentation for more information.
    

    提示是让执行 app.app_context() , 我尝试导入 from start import app 后执行, 又报了循环导入的问题, 想请教这个该怎么解决

    18 条回复    2020-12-21 13:54:30 +08:00
    SjwNo1
        1
    SjwNo1  
       2020-12-19 13:59:48 +08:00
    with current_app. app_context()
    sentanl869
        2
    sentanl869  
       2020-12-19 14:25:01 +08:00
    既然你使用 current_app 而 flask 报 outside of application context,

    说明你的 flask app 根本没有在运行,所以也就没有应用上下文。

    如果只是想完成类的初始化,就想办法 import 你的 app,

    ```python
    with app.app_context():
    class Foo(object):
    ...
    ```

    或者你可以不做上面的改动:

    ```python
    class Foo(object):
    URL = ''

    __init__(self):
    self.URL = current_app.config['EX_URL']
    ```

    在生成实例的的时候再给 URL 属性赋值。
    SjwNo1
        3
    SjwNo1  
       2020-12-19 14:27:55 +08:00
    @SjwNo1 错误理解楼主的意思了,加载类的时候无法获取上下文信息,除非你 create_app (猜测的~
    SjwNo1
        4
    SjwNo1  
       2020-12-19 14:30:41 +08:00
    或者可以把类写在 app.py 下 (逃~
    Lemeng
        5
    Lemeng  
       2020-12-19 14:51:03 +08:00
    学习一下新姿势
    plko345
        6
    plko345  
    OP
       2020-12-19 19:21:31 +08:00 via Android
    @SjwNo1 不能,那就乱了
    plko345
        7
    plko345  
    OP
       2020-12-19 19:23:53 +08:00 via Android
    @SjwNo1 我确实有个 creat_app,,尝试过也不成功,试了不少方式,也查了一些东西,但就是不行
    plko345
        8
    plko345  
    OP
       2020-12-19 19:25:49 +08:00 via Android
    @sentanl869 谢谢解答,如果不行的话只能实例化了
    johnsona
        9
    johnsona  
       2020-12-19 21:56:10 +08:00 via iPhone
    大白话意思就是,你的那断代码不是一个请求来了调用的,而是项目一起来那段代码就执行了
    sentanl869
        10
    sentanl869  
       2020-12-20 00:16:46 +08:00   ❤️ 1
    我脑子下午也是秀逗了,其实根本不是上下文的问题,

    你初始化类使用 app.config 的内容根本不需要上下文。

    既然你有 create_app 那就好办了,我写了个 demo 试了一下,是可以成功初始化类的:

    总共有三个文件:app.pyrun.pyexample.py

    app.py:

    from flask import Flask


    def create_app():
    ____app = Flask(__name__)
    ____app.config['EX_URL'] = 'www.example.com'
    ____return app

    - - - - -

    run.py:

    from app import create_app


    app = create_app()

    - - - - -

    example.py:

    from run import app


    class Foo:
    ____URL = app.config['EX_URL']

    - - - - -

    测试结果:

    >>> from example improt Foo
    >>> Foo.URL
    >>> 'www.example.com'

    所以根本问题是,你这种类初始化完全不该用 current_app,毕竟类初始化的时候 app 没有在运行。

    而 current_app 本质是一个上下文应用的代理,没有 app 在运行自然代理不到任何东西,你被这个报错误导了。

    所以其实你要解决的就是循环引用的问题。
    sentanl869
        11
    sentanl869  
       2020-12-20 00:37:18 +08:00
    我又想了下,想我楼上这么 import app 进行初始化类,运行的时候可不就得循环引用了......

    所以,感觉,你这种初始化类要引用的数据,似乎不该放在 app.config 里,

    而是放在别的地方,比如建个新的独立文件 config.py 什么的
    no1xsyzy
        12
    no1xsyzy  
       2020-12-20 02:21:12 +08:00   ❤️ 1
    我问下,你 Foo.URL 在什么情况下会被使用?

    1. 如果只在实例化后使用,
    1a. 写在 __init__ 里
    1b. 写成 property
    1c. 也可沿用 2. 里的方法。

    2. 如果类可能不会被实例化,
    2a. 写成 staticmethod get_url()
    2b. metaclass 里写成 property (不推荐,“你多半用不上 metaclass”)
    2c.
    from werkzeug.local import LocalProxy
    URL = LocalProxy(lambda: current_app.config['EX_URL'])
    plko345
        13
    plko345  
    OP
       2020-12-20 20:37:33 +08:00
    @sentanl869 额, 我就是放到 config.py 里的, 然后 app 初始化的时候使用里面的配置
    johnsona
        14
    johnsona  
       2020-12-20 21:36:41 +08:00
    @plko345 初始化的时候,你把 app 对象传给你你那个类,或者你手动 push 一下吧
    cs010
        15
    cs010  
       2020-12-21 09:35:12 +08:00 via Android
    确保 from flask import current_app 这句运行之前先 create app
    SjwNo1
        16
    SjwNo1  
       2020-12-21 09:59:55 +08:00
    @cs010 这估计是不行的,因为脱离了应用上下文
    no1xsyzy
        17
    no1xsyzy  
       2020-12-21 11:23:47 +08:00
    @cs010 不存在的,你看官网的样例都没有这么做,甚至在 create_app 里面执行 import xxx
    这句导入就会执行到子模块的 from flask import current_app
    sentanl869
        18
    sentanl869  
       2020-12-21 13:54:30 +08:00
    @plko345 那就试试直接 from config import EX_URL 吧,反正也只是想完成类初始化不是(逃~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2759 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:14 · PVG 20:14 · LAX 05:14 · JFK 08:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.