python-3.x 正在获取“运行时错误:在应用程序上下文之外工作,“当尝试从另一个蓝图导入函数时

cnh2zyt3  于 2023-02-06  发布在  Python
关注(0)|答案(2)|浏览(97)
    • bounty将在3天后过期**。回答此问题可获得+50声望奖励。Eric希望引起更多人对此问题的关注:至少指出我可能做错了什么。
      ***初始说明:**项目使用蓝图,下面是文件结构和所用代码的摘录... *

文件结构:

/app
├── flaskapp/
│   ├── posts/
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── routes.py
│   │   ├── utils.py
│   ├── users/
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── routes.py
│   │   ├── utils.py
│   ├── main/
│   │   ├── __init__.py
│   │   ├── crons.py
│   │   ├── routes.py
│   ├── templates/
│   │   ├── users.html
│   ├── __init__.py
│   ├── config.py
│   ├── models.py
├── run.py

* 帖子/www.example.com utils.py

# Function to get all posts from DB

def get_all_posts():
    post = Post.query.order_by(Post.id.asc())
    return post

用户/www.example.comroutes.py

# Importing 'get_all_posts' function from 'posts/utils.py'

from flaskapp.posts.utils import get_all_posts


users = Blueprint('users', __name__)

#All Users Route + Related Posts

@posts.route("/posts", methods=['GET'])
@login_required
def all_users():
    users = User.query.order_by(User.id.asc())
    return render_template('users.html', USERS=users, POSTS=get_all_posts())

主页/示例网站crons.py

# Importing 'get_all_posts' function from 'posts/utils.py'

from flaskapp.posts.utils import get_all_posts

# A function to be called using 'scheduler' from 'flaskapp/__init__.py' on launch

def list_expired_posts():
    posts = get_all_posts()
    for p in posts:
        if p.expired == 1:
            print(p.title)

scheduler = BackgroundScheduler()
scheduler.add_job(func=list_expired_posts, trigger="interval", seconds=60)
scheduler.start()

# Terminate Scheduler on APP termination

atexit.register(lambda: scheduler.shutdown())

flakapp/初始化. py

# __init__.py Main

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flaskapp.config import Config

db = SQLAlchemy()
login_manager = LoginManager()
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'warning'

# Create APP Function
def create_app(config_class=Config):
    app = Flask(__name__)
    # Import Configuration from Config File Class
    app.config.from_object(Config)

    db.init_app(app)
    login_manager.init_app(app)

    # Import Blueprint objects
    from flaskapp.posts.routes import posts
    from flaskapp.users.routes import users
    from flaskapp.main.routes import main
    
    # Register Blueprints
    app.register_blueprint(posts)
    app.register_blueprint(users)
    app.register_blueprint(main)
    # END

    return(app)

# Calling scheduler function 'list_expired_posts' FROM '/main/crons.py' as a scheduled job to be triggered on app initiation

from flaskapp.main.crons import list_expired_posts
list_expired_posts()

解释:

我有一个位于"posts/www.example.com"中的函数"get_all_posts()",当我导入它并在另一个蓝图的www.example.com文件(*ex.users/routes.py)中使用它时,它工作正常,如上所示。 utils.py' which works fine when I import it and use it in another blueprint'sroutes.py**file (***ex.***users/routes.py) as shown above.
但是当我在另一个蓝图中导入相同的函数时(*特别是.main/www.example.com),我得到了下面的错误,如上所示。crons.py) as shown above.
我尝试使用"main/www.example.com"中"list_expired_posts()"内"posts/www.example.com"中的"get_all_posts()"函数,然后从"flakapp/www.example.com"调用"list_expired_posts()"函数,以便在启动时触发它,并保持每60分钟执行一次。 utils.py
' within the 'list_expired_posts()' in 'main/ crons.py' and then calling the 'list_expired_posts()' function from 'flaskapp/ init.py' to trigger it on launch and keep on executing it every 60 minutes.

错误:

  • 运行时错误:在应用程序环境之外工作。*
  • 这通常意味着您试图使用需要**当前应用程序的功能。要解决此问题,请使用www.example.com_context()**设置应用程序上下文。有关详细信息,请参阅文档。app.app_context(). See the documentation for more information.
    结论注解+尝试的步骤:
  • 我已经暂时删除了"Scheduler",并尝试只使用函数本身,甚至不从"flakapp/www.example.com"调用它。init.py*'.*

我还尝试将下面的代码移到"def create_app(config_class = Config)"部分,但没有成功

from flaskapp.main.crons import list_expired_posts
list_expired_posts()

我还尝试为"crons.py"创建一个特定的蓝图,并将其注册到我的"flakapp/www.example.com",但仍然得到相同的结果。init.py**' but still got the same result.
作为最终结果,我尝试调用"get_all_posts()" FROM**"posts/www.example.com**",然后使用"list_expired_posts()"函数FROM "main/www.example.com"过滤掉"过期的帖子",并安排它每60分钟打印一次过期帖子的标题。 utils.py**', then filter out the 'expired posts' using the 'list_expired_posts()' function FROM 'main/ crons.py' and schedule it to print the title of the expired posts every 60 minutes.
由于我已经排除了调度程序进行测试,我非常肯定这不是调度程序的问题,而是一些我没有弄清楚的导入混淆。
我还意识到,"list_expired_posts()"可以成为"posts/www.example.com"中的另一个函数,然后使用调度程序直接从那里调用该函数,我也尝试过调度程序,但总是得到相同的错误。utils.py**' and then directly call the function from there using the scheduler which I've also tried but keep getting the same error.
我还尝试手动配置应用程序的上下文,如其他职位的指示,但我一直得到同样的错误。

with app.app_context():

我不是一个真正的Python专业人士,我总是尝试寻求多个在线资源之前,张贴在这里的问题,但它似乎像我的运气不好,这一次。您的帮助是真正的感谢。

uqjltbpv

uqjltbpv1#

我也不认为这与调度器有直接关系。我认为它在users/routes.py中工作是因为它位于路线内。所以它只会在您访问该路线时被调用。到那时,您的应用已完全创建,并具有其上下文等。
但是在main/www.example.com中,它不在路由内,所以我认为当它通过您的flaskapp/init.py中的此导入行时,它将尝试运行它crons.py it is not inside a route so I think it will try to run it when it passes this import line in your flaskapp/init.py

from flaskapp.main.crons import list_expired_posts

也许你可以试试这个:将调度器部分放入函数中

主页/示例网站crons.py

# Importing 'get_all_posts' function from 'posts/utils.py'

from flaskapp.posts.utils import get_all_posts

# A function to be called using 'scheduler' from 'flaskapp/__init__.py' on launch

def list_expired_posts():
    posts = get_all_posts()
    for p in posts:
        if p.expired == 1:
            print(p.title)

def initiate_scheduler():
    scheduler = BackgroundScheduler()
    scheduler.add_job(func=list_expired_posts, trigger="interval", seconds=60)
    scheduler.start()

然后在创建应用程序后在www.example.com中调用该函数run.py after you create the app

网站run.py

# first create the app
app = create_app()
# then start the scheduler
initiate_scheduler()

if __name__ == '__main__':
    app.run()
    # if you visit '/posts' in a browser it will call the get_all_posts() 
    # at this point in time after all the other code has ran.
jchrr9hc

jchrr9hc2#

crons.py中没有蓝图,这是意料之中的,因为它是关于调度的,而不是路由。
如果不在路由中,则会得到应用程序上下文丢失的错误,因为不在路由中的所有内容实际上都没有应用程序上下文。
您可能希望查看Flask-APScheduler,您可以使用类似于Flask-SQLAlchemy的方式初始化它,然后在crons.py中使用,它应该透明地携带应用程序上下文。

**NB.**我现在没有时间,但明天会制作一个更长的演示。
**PS.**在users/routes.py中,您定义了users蓝图,但他们似乎在路由装饰器中使用了posts蓝图。

相关问题