Python 启动flask应用程序后运行代码

Python 启动flask应用程序后运行代码,python,flask,flask-script,Python,Flask,Flask Script,我的目标是让任意代码在Flask应用程序启动后运行。以下是我得到的: def run(): from webapp import app app.run(debug=True, use_reloader=False) 理想情况下,我可以这样做: def run(): from webapp import app app.run(debug=True, use_reloader=False) some_code() 但是代码不会在app.run()之后继

我的目标是让任意代码在Flask应用程序启动后运行。以下是我得到的:

def run():
    from webapp import app
    app.run(debug=True, use_reloader=False)
理想情况下,我可以这样做:

def run():
    from webapp import app
    app.run(debug=True, use_reloader=False)
    some_code()
但是代码不会在app.run()之后继续运行,因此一些代码()永远不会运行

我目前正在研究的解决方案是在app.run()的单独线程中运行一些_code(),创建一个函数来设置:

app.is_running = True
然后获取一些_code(),向应用程序发送一个基本请求,以便“在第一个请求之前”代码运行。这相当复杂,很难记录下来。我宁愿使用烧瓶中已经提供的app.is\u running参数,或者使用
@app.after\u server\u启动
decorator,但据我所知,这两个参数都不存在

帮我把代码做得更好


死后:每次我想到这个问题,我都希望有一个
@app.after\u server\u start
decorator存在。

用于运行你的应用程序,然后像这样覆盖runserver类/方法

# manage.py

from flask_script import Manager

from myapp import app

manager = Manager(app)

def crazy_call():
    print("crazy_call")

@manager.command
def runserver():
    app.run()
    crazy_call()

if __name__ == "__main__":
    manager.run()

如果您需要在flask应用程序启动后但严格地在第一个请求之前执行某些代码,甚至在第一个请求执行时都不会触发@app。在第一个请求可以处理之前,您应该使用flask_脚本,正如CESCO所说,但您可以对类服务器进行子类化,并覆盖uuu u调用方法,而不是用@manager.command覆盖runserver命令:

from flask import Flask
from flask_script import Manager, Server

def custom_call():
    #Your code
    pass

class CustomServer(Server):
    def __call__(self, app, *args, **kwargs):
        custom_call()
        #Hint: Here you could manipulate app
        return Server.__call__(self, app, *args, **kwargs)

app = Flask(__name__)
manager = Manager(app)

# Remeber to add the command to your Manager instance
manager.add_command('runserver', CustomServer())

if __name__ == "__main__":
    manager.run()

这样,您就不会覆盖runserver命令的默认选项。

我在flask应用程序中遇到了同样的问题。我想在应用程序启动时启动一个调度程序,定期启动一些作业。由于我在docker容器中部署了我的应用程序,因此我最终添加了一个“健康检查”端点,该端点只返回200,并在docker文件中配置了该端点:

HEALTHCHECK CMD curl——失败http://localhost:8080/alive ||退出1

默认行为是每30秒执行一次该命令,第一次运行方便地启动init()方法。

我刚刚做了(在用
python main.py执行的
main.py
中):

与app.app\u context()
从模块导入一些_代码
一些_代码()
def run():
从webapp导入应用程序
运行(debug=True,use_reloader=False)
没有上面提供的更全面的答案,这对我来说是有效的。在我的例子中,
some\u code()
正在通过
flask\u caching.cache
初始化缓存


但这可能取决于某些代码到底在做什么…

我并不喜欢上面提到的任何方法,因为这样做不需要Flask脚本,而且不是所有的项目都会使用Flask脚本

最简单的方法是构建您自己的Flask子类。如果你用Flask(\uuuu name\uuuuu)
构建你的应用程序,你只需添加你自己的类并使用它即可

def do_something():
  print('MyFlaskApp is starting up!')


class MyFlaskApp(Flask):
  def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
    if not self.debug or os.getenv('WERKZEUG_RUN_MAIN') == 'true':
      with self.app_context():
        do_something()
    super(MyFlaskApp, self).run(host=host, port=port, debug=debug, load_dotenv=load_dotenv, **options)


app = MyFlaskApp(__name__)
app.run()
当然,它不会在启动后运行,而是在最后调用
run()
之前运行。使用应用程序上下文,您应该能够对数据库或任何其他需要应用程序上下文的操作进行任何操作。这也适用于任何服务器(uwsgi、gunicorn等)

如果您需要
do\u something()
是非阻塞的,您可以简单地使用
threading.thread(target=do\u something.start()
对其进行线程化


条件语句用于在使用调试模式/重新加载程序时防止双重调用。

如果要在flask运行后运行一组命令(作为常规Py应用程序),请使用多处理库(例如),在该解决方案中,您可以在系统程序旁边使用API/Web应用程序

import flask
from flask import request, jsonify,make_response
import time
import multiprocessing

app = flask.Flask('__name__')

def API(Conf):
   print('In API selction')
   app.run(host='0.0.0.0', port=1337,)
if __name__ == "__main__":
   config = {"Something":"SomethingElese"}
   p = multiprocessing.Process(target=API, args=(Conf,))
   p.start()
   #time.sleep(3)
   print('After Flask run')
注:以上代码只是一个示例/想法。可能有一些错误。(但我在生产区使用了这种解决方案,它很好。)


附言:(在我看来)这个解决方案的问题是:调试部分更加困难。

为什么不在第一次请求之前使用
@app.
并完成它呢。为什么代码需要提前运行?换句话说,为什么在启动服务器后运行代码如此重要(无论如何,您不能像在生产代码中那样使用它,请始终使用适当的WSGI容器,而不要使用仅用于开发的脆弱的Werkzeug服务器,该服务器是从
app.run()
启动的)但是在请求到达之前?主要是因为在服务器启动后运行代码更有意义,但您有权要求它实际上不需要在导入时运行代码,或者在第一个请求之前运行代码。可能的回答是。还有“死后”不是“后腐殖质”。对不起。我不得不这么做。谢谢你的帖子。当我们的应用程序通过uwsgi运行时,我们如何集成此管理器?它对我不起作用。我必须像下面这样交换行:app.run()和crazy_call()。我有一个查询,在部署我的应用程序后,将
manager.run()
连续24小时运行,或者当用户点击url时,是否只有?我知道这看起来可能是个愚蠢的问题,但我想知道,在我的情况下,我只需要一个由IIS启动的备份进程(worker),而且这种方法很有效(即使是离开super(MyFlaskapp,self.run row out),这一个对我来说很有效。非常感谢。