首页 > 编程问答 >Python 中的工作队列 - 我错过了什么吗?

Python 中的工作队列 - 我错过了什么吗?

时间:2024-07-24 16:52:33浏览次数:14  
标签:python worker dill

这可能会被标记为重复或可能不相关。但我实际上相信这个问题对我和未来缺乏经验的 Python 开发人员都很重要。

由于 GIL,用于 CPU 密集型任务的本地工作队列的概念在 Python 中至关重要。这方面SE上有明显的答案。使用子进程的方法来绕过缺乏真正的CPU有限并行性的问题。在Python中我们可以使用 multiprocessing.Pool 类来实现这一点。我想构建一个 通用工作队列单例 ,它可以接受任何函数和任何类型的参数,并在不同的CPU上沿着我的主进程异步处理它,就像工作队列应该的那样。

就是这样很简单。

只是事实并非如此。

问题的基础在于 Pickle 问题。 据我发现,泡菜是有限的。请参阅 这个问题 因为一次可以有类似以下的代码:

def NetworkClassType(topologyClass):
    class Network(topologyClass):
        ...

Pickle 不是通用工作队列的选项。所以我发现我可以使用 dill 然而,我不断遇到一系列必须解决的问题。 从 这个 问题开始。我必须使用此设置,因为我的目标是通用 WQ,有时事情并不在子流程期望的上下文中。

然后我遇到了一个问题,其中来自 pickle 包的代码:

if reduce is not None:
    rv = reduce(self.proto)

返回异常 TypeError: 'NoneType' object is not callable ,找出原因是一场噩梦。事实证明,当您将以下代码放入 pickled 类(即使是在 dill 中)时,以下代码会破坏 if 语句:

def __getattr__(self, prop):
    return None

这基本上意味着您在尝试获取不存在的属性时不希望出现任何异常在类的 __dict__ 中定义。事实证明,pickle 和 dill 无法处理此代码。已经有了通用的 WQ 想法。

但是,好吧,让我们通过从类中删除上面的代码来摆脱这种奇怪的情况。

然后我遇到了 这个错误 ,其中有多个关于如何处理的建议来解决,没有一个真正适合我的情况。

此时,我停了下来。我心想,“我在这里做错了。Python 是一种面向数据的语言,成熟,具有完善的回显系统。通用的工作队列不可能这么复杂。一定有人在我之前做到了这一点。”|| |所以为了明确起见,我在这里自责。我一定错过了什么。 python 中有一个众所周知的 WQ 包吗?也许多处理不是答案?也许莳萝不是答案?也许有一种方法可以绕过 GIL(无需

更改解释器 )?也许我在 SE 的某个地方错过了对所有这些问题的一个简洁答案? 现在我可以继续这样做,我会的。一次解决一个问题,直到弄清楚如何实现我的目标。但如果有人告诉我我错了,我会很高兴。事实上,Python 中有一个工作正常的通用工作队列(或者更好,一个

Actor 队列 ),它可以处理所有事情并且效率很高。 我只能希望。

谢谢.

我仍在从事该项目。 我尝试了上述所有链接(然后是一些链接),并将尝试了解如何使我的 WQ 包工作。

编辑:我忘记解决可能出现的一个明显问题,即操作系统的问题。显然,即使是通用的 WQ 在不同的操作系统上也可能会失败。我的目标是 Windows 10 及以上版本。

EDIT: I forgot to address an obvious question that might arise and that is of the OS. Obviously, even a generic WQ might fail on different OS. Mine is aimed for windows 10 and above.


你对 Python 中工作队列的深入研究,以及你遇到的“pickle 问题”表明你对这个问题有很好的理解。你问对了所有的问题,并且像你一样,很多开发者在寻找一个“通用的”工作队列解决方案时都感到很沮丧。

让我们来分解一下问题,并探索一下可用的选项:

你所面临的挑战

  • Pickle 的限制 : 你说得对, pickle (以及一定程度上的 dill )在处理复杂的对象,例如嵌套函数、lambda 或者带有 __getattr__ 之类魔法方法的类时,会有局限性。这些限制源于 Python 代码执行的动态本质,使其难以在进程之间序列化所有内容。

  • 通用的痛点 : 创建一个真正通用的工作队列,可以处理任何函数或数据结构,在 Python 中,或者说在任何语言中,都是一项艰巨的任务。总是有可能出现边缘情况,或者依赖于特定库或配置的代码,而这些代码不能轻易地序列化或反序列化。

可选方案

  1. 拥抱限制

  2. 简化你的函数 : 如果你能将你的工作函数设计成独立的、可以被 pickle 轻松序列化的函数,那么 multiprocessing.Pool 就能很好地工作。这通常涉及到将任何复杂的状态或依赖项传递到函数参数中(确保这些参数也是可序列化的)。

  3. 自定义序列化 : 对于棘手的对象,你可以探究 pickle __reduce__ dill 的扩展机制,以实现自定义的序列化和反序列化逻辑。这需要一些工作量,但可以提供更大的灵活性。

  4. 探索其他工作队列库

  5. Celery : 虽然通常用于分布式任务队列,但 Celery 也可以用于本地多处理。它提供了强大的功能,例如任务调度、重试以及与各种消息代理的集成。然而,它也带有更大的复杂性,可能需要更多的设置。

  6. RQ (Redis Queue) : RQ 是一个更简单的任务队列,它使用 Redis 作为消息代理。它易于使用,并且可以很好地处理通用函数,但它依赖于 Redis 服务器。
  7. Gearman : Gearman 是一个通用的分布式工作队列系统,支持多种语言,包括 Python。它可以处理比简单的进程间通信更复杂的工作流程。

  8. 考虑替代架构

  9. 异步编程 : 对于 I/O 密集型任务,异步编程(使用 asyncio 库)可以是更有效率的解决方案。它允许在单个线程中并发执行代码,从而避免了 GIL 问题。

  10. 微服务 : 对于更大型或更复杂的系统,你可以考虑将你的应用程序分解成更小的、独立的微服务,这些微服务通过网络进行通信。这种方法提供了更大的灵活性,并且可以利用不同的技术和语言。

没有银弹

选择最佳方案取决于你的具体需求和限制。

  • 简单性与功能 : multiprocessing.Pool 易于使用,但功能有限。Celery 和其他工作队列提供了更多的功能,但增加了复杂性。
  • 性能 : 进程间通信的开销很大,因此,如果性能至关重要,那么你可能需要探索其他架构,例如异步编程或微服务。
  • 可维护性 : 选择一个对你和你的团队来说易于理解和维护的解决方案非常重要。

最后的想法

你对 Python 工作队列的深入研究值得赞赏。不要气馁,因为没有找到通用的解决方案。专注于你的特定需求,并选择最适合你的用例的方案。记住,即使是最复杂的系统通常也是从更简单的构建块开始构建的。

标签:python,worker,dill
From: 78787203

相关文章

  • Python ctypes OSError:[WinError 1114]动态链接库(DLL)初始化例程失败
    我试图使用Python中的ctypes库调用C++函数:test.pyfromctypesimport*fromrandomimportrandinttester=cdll.LoadLibrary('./test.dll')print(tester.test(randint(1,100)))test.cpp#include<vector>intcppTest(intnum){std:......
  • Python 的分布式锁管理器
    我有一堆具有多个实例的服务器,这些实例访问的资源对每秒的请求有硬性限制。我需要一种机制来锁定所有正在运行的服务器和实例对此资源的访问。有我在github上找到的一个restful分布式锁管理器:https://github.com/thefab/restful-distributed-lock-manager不幸......
  • 如何在Python中提示self变量的类型
    通常不需要关心Python类成员函数中的self变量,但我正在实现一个装饰器,看起来像defextractor(depends:List[Text]=None,provides:List[Text]=None)->Callable[[ExtractorFunction],Extracto......
  • 将 Python 类型提示限制为元组中的值
    我的方法之一采用status中使用的filter()参数。此参数与定义如下的模型字段相关:STATUS_CHOICES=((1,_("draft")),(2,_("private")),(3,_("published")),)classMyModel(Model):status=models.PositiveSmallIntegerFi......
  • 在python中查找区间数据的中位数
    我正在探索不同的python库,我想知道如何找到分组数据集的近似中值。这里有一个表格供参考。年龄频率1-1012310-203502......
  • 比较Python中的字符串统一特殊字符
    也许我可以使用更好的英语,但我想要的是忽略单词中的重音(和类似的),所以:renè、rené、rene'和rene应该是相同的,所以应该mañana和manana或even-distribuited和evendistribuited,可能还有sho......
  • 如何使用 Python 脚本从客户账单电子邮件中获取订单 ID - WooCommerce API
    我想创建一个python脚本,返回只知道客户的账单电子邮件的订单。我尝试这样做,但返回所有最近的订单:fromwoocommerceimportAPIwcapi=API(url="https://siteexample.com",consumer_key="ck_xxx",consumer_secret="cs_xxx",version="wc/v3")......
  • python基础理论小总结
    1.python语言的特性Python是一门解释型语言,简单清晰,开源免费,跨平台,有大量第三方库辅助开发,支持面向对象与自动垃圾回收,方便与其他编程语言相互调用。Python在数据采集、人工智能、WEB后台开发、自动化运维、测试等方向应用广泛。2.解释型语言和编译型语言的区别执行方式不......
  • python编码规范
    本篇讲的是代码格式化的问题,解决格式化的方法在最下方,不想看内容的,滑到最下方就好了。一、变量的命名规则1.组成:字母、数字、下划线2.不可以以数字开头3.不建议使用下划线开头4.命名需见名知意5.不要与关键字重名。如何查找所有关键字?importkeywordprint(keyword.k......
  • Python爬虫开发中的常用库与框架安装指南
    在Python爬虫开发中,选择合适的库和框架可以大大提高开发效率和爬虫的性能。本文将介绍一些常用的解析库、请求库、储存库、Web库、App爬取库以及爬虫框架,并展示如何使用pip命令进行安装。一、解析库1.BeautifulSoupBeautifulSoup是一个用于从HTML或XML文件中提取数据的Pyth......