如何 运行 Python 3 即使在用户关闭网络 browser/tab 后仍能正常运行?

How to run Python 3 function even after user has closed web browser/tab?

我在处理我正在处理的 python 项目时遇到问题(我通常使用 PHP/Java,所以缺乏一些知识)。 基本上我有一个使用 Flask 构建的 python 程序,它使用 Shopify Python API.

将库存管理系统连接到 Shopify

当用户通过 AJAX 请求触发功能时,我需要启动一个 function/process 通过 Shopify API 更新客户 Shopify 商店中的产品。这大约需要 2 小时(约 7000 种产品,而且必须先从库存管理系统中提取它们)。 问题是我需要一种可以触发此 function/process 的方法,即使客户端关闭浏览器 function/process 也会继续 运行.

如果有任何方法我可以用这个背景的当前进度更新前端function/process,那就太棒了。

如果有人知道完成此任务的任何库或资源,将不胜感激。 我有一个 google,但我能找到的所有解决方案似乎都是针对 CLI 脚本而不是 Web 脚本的。

多谢, 科里 :)

通常您会创建一个任务,然后 return 向用户提供一个 id,他可以使用它来汇总所述任务的状态。

然后您将在另一个 container\process\thread 中处理任务。

Celery 是一个 Python 库,可以帮助您进行设置。

另一种常见的解决方案是使用 publisher\subscriber 设计并使用分布式队列,例如 Kafka、RabbitMQ 甚至 Redis。

事实上,Celery 可以使用 RabbitMQ 或 Redis 作为其消息代理。

您需要异步处理此任务,因为它是一项耗时 运行 的作业,会显着降低 HTTP 响应的性能(如果您等到它完成)。

此外,您可能会注意到您需要 运行 在为您的 HTTP 请求提供服务的当前进程的单独进程中执行此任务。因为,Web 服务器(Gunicorn、uWSGI 等)将生成它们创建的进程并在需要时释放系统资源。您很容易会遇到这样的情况,即通过 Ajax 启动的异步进程将被 Web 服务器中断并终止,因为您关闭了浏览器(请求已关闭)。因此,threadingcoroutines 不是完成此任务的最佳工具。

这就是为什么有一些很棒的 Task queue 项目可以解决您的问题。我们可能会注意到:

  • Celery: (Production ready solution) 一个专注于实时处理的任务队列,同时也支持任务调度。作为消息代理与 RedisRabbitMQ 配合使用效果很好
  • RQ (Redis Queue):RQ(Redis 队列)是一个简单的 Python 库,用于排队作业并在后台与工作人员一起处理它们。它由 Redis 支持,旨在降低进入门槛。它可以很容易地集成到您的网络堆栈中。
  • Taskmaster: Taskmaster 是一个简单的分布式队列,专为处理大量一次性任务而设计。
  • Huey:是一个基于Redis的任务队列,旨在为执行任务提供一个简单而灵活的框架。 Huey支持任务调度,类似crontab的重复任务,结果存储,失败自动重试。
  • Dramatiq:是 Celery 的快速可靠替代品。它支持 RabbitMQ 和 Redis 作为消息代理。
  • APScheduler: Advanced Python Scheduler (APScheduler) 是一个 Python 库,可让您安排 Python 代码稍后执行,一次或定期执行.

还有更多!

随着 micro services 的兴起,您可以结合 Task queuescontainers 的强大功能,构建一个单独的容器来处理您的长 运行ning 任务(并根据当前情况更新您的数据库)。此外,如果您还不能使用 micro services 架构,您可以构建一个单独的服务器来处理这些任务,并使处理用户请求的 Web 服务器免于 运行 长时间 运行宁任务。

最后,您可以像这样在您当前的网站中组合这些解决方案:

  • 用户点击按钮。
  • Ajax 请求触发您的后端(通过 API 或其他方式)
  • 您现在或稍后(在单独的 container/VPS... 中)运行 在代理消息中安排任务
  • 在您的后端,您检索任务的 Task ID
  • 你 return API 的 Task ID 或其他任何东西,然后将其添加到会话 cookie 或单独的 table 中,它与启动该过程的用户打交道.
  • 在某些 JS 中,您不断通过 Task ID 从后端请求任务的状态(在用户会话 cookie 或数据库中)
  • 即使用户关闭了他的浏览器,该任务也会继续其操作,直到它完成或引发异常。在您已经拥有的任务 ID 中,您可以轻松了解此任务的状态并将此信息发送给用户(在他再次登录时的视图中,通过电子邮件等...)

当然你可以改进这个场景!