Flask入门:falsk可以多线程吗?

   日期:2024-12-27    作者:z2z85 移动:http://oml01z.riyuangf.com/mobile/quote/59120.html

你知道在 Flask 中可以使用线程吗?

我们将在以下部分中对此进行细分:

  • Flask 是多线程的
  • 可以在 Flask 中添加线程吗
  • flask 是否支持多个客户端
  • 如何在后台运行 Flask 任务

我们将逐点介绍一些代码片段来了解如何实现这一点

默认情况下,Python Flask 框架是多线程的。

此更改发生在 1.0 版本中,他们引入了线程来处理多个新请求。使用它,Flask 应用程序在后台的工作方式如下:

  • 来自在线客户端的网络请求
  • Flask 接受连接并注册一个请求对象
  • 在执行任何处理之前,Flask 会在内部将连接注册到它的队列中以处理
  • 完成此操作后,Flask 会创建一个轻量级线程来处理请求,并在线程池中跟踪它
  • 线程从池中使用,并使用标准 Python 解释器进行处理
  • 线程消耗的调度和优先级排序完全取决于 Python 如何处理它

正如你在上面看到的,这个过程是相当标准化的,通常是大多数 Python 程序所做的。需要注意的重要部分是,您仍然受 Python 调度程序的摆布,对此您无能为力。此外,您依靠 GIL(全局解释器锁)来激活或停用每个线程上的特定操作。因此,CPU 时间通常是根据需要执行的代码或是否要执行 I/O 操作来给出的。我发现 CPU 时间分配得相当好,总的来说,事情几乎一帆风顺,没有任何特别的问题。

答案是肯定的。正如我们之前所讨论的,Python Flask 现在提供开箱即用的线程,因此您无需执行任何操作即可激活它。这里的问题是要了解它仍然具有任何其他使用线程的 Python 应用程序的限制。由于 Python 默认情况下不是一种多进程语言,因此往往会进行上下文切换,因此所有内容都在一个 CPU 内执行。

Flask 多线程处理

这意味着,当你调用 Python 解释器时,除非你明确使用类似 multi-processing 的东西,否则没有其他进程会从它分叉出来在单独的 CPU 上运行。话虽如此,当 Python Flask 依赖于扩展 CPU 密集型作业时,这在性能方面有点阻碍了它的能力,因为其他一切都必须等待它完成(异步)。尽管如此,您通常希望将持久作业放在具有自己控制权的单独线程中,或者使用 Celery 将其作为单独的后台任务发送。

简短的回答是肯定的,您可以在 Flask 应用程序中使用多线程。然而,有一个问题。当您使用线程局部变量时,目前这些局部变量没有得到很好的支持,这意味着如果您需要在线程之间进行任何同步或信息共享,您将很难实现它。

 Flask 在设计时并没有考虑到线程。话虽如此,请记住,您正在执行违背应用程序设计原则的操作,这可能会导致问题。使用线程的方式完全是在后台运行任务,而不必等待它,更像是一种即发即弃的方法。

如果您尝试创建线程池并需要同步,则问题会变得更糟。想想几乎大多数 Flask 线程都运行后被遗忘的场景,这使得管理它们之间的事情变得困难,因为没有信息的共享资源。使 logic 复杂化并在其中添加另一个层,可能会抵消您以前使用 threads 的所有优势。根据我的经验,这是一个警告,要避免它,只坚持使用基于处理网络事件的 Flask 模型。

所以现在我们已经了解了为什么 Flask 的设计不适合线程,我们将讨论如何使用 Python 线程在 Flask 中对任务进行后台处理。下面的代码 snipet 将是有关如何执行此操作的良好第一步:

我们要做的第一步是定义一个线程函数,我们将作为后台 Python 任务执行该函数。为此,我们将从线程 Python 库继承 Thread 类,并定义包含我们想要执行的代码的新 run 函数。

在下面的示例中,我们将此字段留空,并仅打印一条消息,以确保我们的任务在后台成功执行。在实际情况下,您希望在 print out 函数之前使用自己的代码填充它,以便它可以执行您需要的任何内容。

现在我们已经定义了线程 Python 函数,我们所要做的就是开始定义我们的主 Flask 应用程序并调用我们的线程调用。为此,我们将实现一个代码 snipet,如下所示。

让我们逐行来看

  • 首先,我们将新路由定义为 /api/background-task,这也是要附加的主 Flask URL 的前缀路径
  • 我们现在接受的方法只是一个 GET 请求,用于演示我们的线程示例
  • 我们的 implementation function 基本上是通过首先初始化我们之前定义的新 threaded task 类的实例(它继承自 Python 的父级多线程库)来工作。
  • 然后,我们只需通过调用 start 函数来启动它
  • 我们可以选择使用 join 等待函数完成,请注意,如果您想触发并忘记并且不关心它会发生什么,则无需执行此操作。但是,您需要注意,当您尝试终止 Flask 应用程序时,如果您的线程仍在运行,则需要使用 join 等待它,否则您将面临线程未终止的风险。通常,最好将所有调用的线程对象放在一个池中,并监视它们是否仍在运行并且尚未过期/崩溃。这将防止内存泄漏,并让您更好地控制线程中发生的事情。它将进一步允许您通过轮询线程的状态和其他内容来监控线程。
  • 最后,函数完成后,我们只需返回一个带有自定义 JSON 状态代码的 200,指示在任务执行过程中一切正常。

这里有一些事情我们需要注意,每个 Python 多线程应用程序都附带这些事情:

  • 如上所述,在终止 Flask 应用程序之前,需要完成所有线程
  • 任何线程同步都需要在终止之前进行,因此如果您的线程正在执行重要的数据库操作或类似操作,则需要确保它得到正常清理。
  • 线程是两把刃剑,如果你依赖于一个公共数据存储,并且你正在使用互斥锁,那么在一段时间后要非常小心地释放互斥锁,否则你最终可能会陷入死锁情况,你的整个应用程序将锁定。更糟糕的是,如果你的 Flask 应用程序已经生成了一个线程,并且它正在等待它加入并完成,那么为 Web 请求提供服务的 Flask 线程也将锁定。

为避免这些问题,请确保使用 Python 线程最佳实践实现和处理此问题,其中最重要的做法是我之前谈到的。


特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号