【问题标题】:Can I have Python code to continue executing after I call Flask app.run?我可以在调用 Flask app.run 后让 Python 代码继续执行吗?
【发布时间】:2018-04-10 20:46:48
【问题描述】:

我刚刚开始使用 Python,尽管过去 30 年来我一直在使用其他语言进行编程。我想让我的第一个应用程序保持简单,所以我从一个托管在 Raspberry Pi 上的小型家庭自动化项目开始。

我的代码可以正常工作(控制阀门、读取流量传感器并在显示屏上显示一些数据),但是当我想添加一些 Web 交互性时,它突然停止了。 我在该主题上找到的大多数文章都建议使用 Flask 框架来编写动态网页。我已经尝试并理解了 Flask 的基础知识,但是一旦我调用“app.run”函数,我就无法解决 Flask 阻塞的问题。我的 python 代码的其余部分等待 Flask 返回,这永远不会发生。 IE。不再需要水流量测量、阀门电机转向或显示更新。

所以,我的基本问题是:我应该使用什么工具来提供一个简单的动态网页(负载非常低,例如 1 个请求/周),与我的应用程序主要任务(GPIO/脉冲计数)并行)?所有这一切都在 Raspberry Pi (3) 的资源受限环境中进行。 如果您仍然建议使用 Flask(因为它似乎非常接近目标),我应该如何安排我的代码以继续处理现实世界的事件,例如上面提到的?

(如果没有看到实际代码,这最后一部分可能很难回答,但也许可以以“通用”方式回答它?或者指向我在搜索时可能错过的现有示例。)

【问题讨论】:

    标签: python multithreading asynchronous flask


    【解决方案1】:

    您在多线程方面走在了正确的轨道上。如果你的监控代码循环运行,你可以定义一个类似

    的函数
    def monitoring_loop():
        while True:
            # do the monitoring
    

    然后,在调用app.run() 之前,启动一个运行该函数的线程:

    import threading
    from wherever import monitoring_loop
    
    monitoring_thread = threading.Thread(target = monitoring_loop)
    monitoring_thread.start()
    
    # app.run() and whatever else you want to do
    

    不要join 线程 - 您希望它继续与您的 Flask 应用程序并行运行。如果你加入它,它会阻塞主执行线程直到它完成,这永远不会,因为它正在运行一个while True 循环。

    要在监控线程和程序的其余部分之间进行通信,您可以使用queue 在它们之间以线程安全的方式传递消息。

    【讨论】:

    • 哇! 10 分钟内给出中肯的答复。你只需要爱上 StackOverflow!我可以粗鲁地要求指向使用这种技术的一些工作代码的指针吗? (只是为了在更大的背景下理解它)。
    • 恐怕我个人手边没有任何简洁的例子,但上面的PyMOTW 3 post 帖子看起来像是一个简短的例子很好的介绍。
    【解决方案2】:

    我可能会处理这个问题的方法是将您的程序分成两个不同的单独运行的程序。

    一个程序处理 GPIO 监控和通信,另一个程序是您的小型 Flask 服务器。由于它们作为单独的进程运行,因此它们不会相互阻塞。

    您可以让两个进程通过一个小型数据库进行通信。 GIPO 接口可以定期将流量测量或其他相关数据记录到数据库中的表格中。它还可以监视数据库中可能用作请求队列的另一个表。

    您的 Flask 实例可以查询同一个数据库以获取当前统计信息以返回给用户,并且可以根据用户输入将条目提交到请求队列。 (如果 GIPO 进程将请求队列更新为当前状态,Flask 进程可以将其报告回来。)

    至于在小型 Raspberry Pi 上使用哪种数据库,请考虑 sqlite3,它是一个非常小的、轻量级的基于文件的数据库,作为 Python 中的标准库得到了很好的支持。 (它不需要运行完整的“数据库服务器”进程。)

    祝你的项目好运,听起来很有趣!

    【讨论】:

      【解决方案3】:

      您好,我正在尝试与dronekit_sitl 连接,但遇到了同样的问题,30 秒后连接关闭。要摆脱这种情况,有 2 个解决方案:

      1. 您使用装饰器 before_request:在这个装饰器中,您定义了一个方法,该方法将在每个请求之前处理连接
      2. 您使用装饰器 before_first_request:在这种情况下,一旦调用第一个请求,就会建立连接,您可以使用全局变量处理另一条路由中的对象

      欲了解更多信息https://pythonise.com/series/learning-flask/python-before-after-request

      【讨论】:

        猜你喜欢
        • 2021-09-09
        • 2021-02-26
        • 2012-10-25
        • 1970-01-01
        • 2014-12-14
        • 1970-01-01
        • 2022-11-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多