Python 在Flask development server重新加载时向前端发送消息

Python 在Flask development server重新加载时向前端发送消息,python,flask,Python,Flask,我想发送一个服务器发送事件,以便在服务器重新加载时更新前端。我知道您可以通过设置Flask\u ENV=development自动重新加载烧瓶。是否有像“onServerReload”这样的回调函数在服务器刷新之前或之后调用?不是真正的解决方案,但对于注释来说太长了 烧瓶实际上使用了Werkzeug的重装器。此处打印出短语*在“/chat/app.py”中检测到的更改,重新加载: 有一个钩子的想法,似乎早在年就被讨论过了,但从未实现过。其论点似乎是,当实际重新加载应用程序时,整个程序将再次运行,

我想发送一个服务器发送事件,以便在服务器重新加载时更新前端。我知道您可以通过设置
Flask\u ENV=development
自动重新加载烧瓶。是否有像“onServerReload”这样的回调函数在服务器刷新之前或之后调用?

不是真正的解决方案,但对于注释来说太长了

烧瓶实际上使用了Werkzeug的重装器。此处打印出短语
*在“/chat/app.py”中检测到的更改,重新加载

有一个钩子的想法,似乎早在年就被讨论过了,但从未实现过。其论点似乎是,当实际重新加载应用程序时,整个程序将再次运行,因此:

from flask import Flask
app = Flask(__name__)
print ('I have been reloaded')
# Rest of file
重新加载时会导致:

 * Detected change in '/chat/app.py', reloading
 * Restarting with stat
I have been reloaded
您可以在这里放置一些代码,将某些内容发送到流,并将其包装在
if
子句中,以确保它只在dev中运行。如何实际实现这一点可能取决于您已经获得了什么


我克隆了这个repo:它是苏格兰和南方能源公司的一个基本实现,以redis pub/sub作为代理,使它看起来像:

red = redis.StrictRedis(host='redis')
# This will happen on init
red.publish('chat','Just Reloaded')

然而,我遇到的问题是,当我发布“刚刚重新加载”消息时,由于应用程序处于重新加载状态,因此该频道没有订户(订阅发生在
事件流()
函数中,当有人点击
/stream
路径时调用该函数)

如果通过保存对代码的更改来激活重新加载程序,并查看浏览器的“网络”选项卡,您将看到第一个流关闭,几秒钟内另一个流打开到同一端点。发布命令发生在这些点之间,因此从未到达前端。我理解这是redis的局限性


一个解决办法可能是有一个专门的flask服务器,它只处理事件流,并订阅一个redis频道,开发中的应用程序也可以发布到该频道。然后,开发中的应用程序从前端连接到该流,在重新加载代码时,订阅不会中断,因为它由专用的flask实例提供服务。但是,如果在不同的端口上访问每台服务器,浏览器可能会抱怨。

对flask
werkzeug/\u-reloader.py:ReloaderLoop进行一些研究后,在第160行使用\u-reloader重新启动\u。我发现它使用
os.environ[“WERKZEUG\u RUN\u MAIN”]
检查当前进程是监视进程还是主服务器进程。一旦触发重新加载事件,将调用
trigger\u reload
,只需调用
sys.exit(3)

在开发模式下,我的出路如下:

def main():
    if os.environ.get("WERKZEUG_RUN_MAIN") == "true":
        # If we want to do something **ONLY WHEN** true main serve process is started
        do_something_only_when_real_server_process_started()

    try:
        app.run(debug=True)
    except SystemExit:
        do_something_when_reload_triggered_before_process_exit() # <-- 
        sys.exit(3) # see werkzeug/_reloader.py line 184
def main():
如果os.environ.get(“WERKZEUG_RUN_MAIN”)=“true”:
#如果我们想做点什么**只有在**真正的主发球过程开始时
只在真正的服务器进程启动时做某事()
尝试:
app.run(debug=True)
除系统退出外:

是否在重新加载时触发?在处理退出()之前触发?#“更新前端”是什么意思?接收服务器发送事件并刷新HTML页面。请参阅此问题。它讨论了如何从服务器发送事件。使用javascript在客户端重新加载很容易。是的,推送不是问题,而是来自服务器端的事件。一旦我看到事件,链接本身就很有用。你试过了吗?我不确定它如何与启用调试的服务器交互,但从文档来看,它似乎可以工作。因此,基本上前端重新加载程序不会以这种方式工作,因为浏览器选项卡和新重新加载的服务器之间缺少连接。。。。。我猜必须注册“服务器关闭”,然后刷新选项卡将尝试连接到新服务器(mayber,超时)Javascripts
EventStream
在链接的repo中实现,一旦服务器重新加载,就会自动重新连接到
stream/
端点。不需要刷新选项卡。这个实现中的问题是,在我的python示例中,当运行
publish
命令时,以前的服务器已经死了,但它还没有为新的
/stream
端点提供服务。几秒钟后,它会连接到客户端,但由于redis pub/sub的工作方式,客户端将永远看不到已发布的消息,因为该消息在发布时未订阅。