0

我编写了一个 irc 机器人,它在被告知时运行一些命令,这些命令是预定义的 python 函数,将在运行机器人的服务器上调用。

我必须在不知道它们会做什么的情况下调用这些函数(更多的 I/O 或计算成本高的东西,因为我在接受它们时会查看它们,所以没有什么害处),但我需要获取它们的返回值才能给出答复回到irc频道。

您推荐使用哪个模块来并行运行这些回调中的几个,为什么?

threadingor模块,还有multiprocessing别的吗?

我听说过 twisted,但我不知道它如何适合我当前的实现,因为我对此一无所知,而且从协议的角度来看,该机器人功能齐全。

还要求命令异步执行操作不是一种选择,因为我希望机器人易于扩展。

4

2 回答 2

2

您的问题没有明确的答案:这实际上取决于函数的作用、调用频率以及您需要的并行度。

threading和模块以完全不同的multiprocessing方式工作。

threading在 Python 解释器中实现本机线程:创建起来相当便宜,但由于 Python 的全局解释器锁 (GIL),并行性受到限制。线程共享相同的地址空间,因此可能会相互干扰(例如,如果一个线程导致解释器崩溃,所有线程,包括您的应用程序,都会死掉),但线程间通信因此既便宜又快速。

multiprocessing使用不同的进程实现并行:设置比线程昂贵得多(需要创建一个新进程),但每个进程都运行自己的解释器副本(因此没有与 GIL 相关的锁定问题)并在不同的地址空间中运行(隔离你的主应用程序)。子进程通过 IPC 通道与父进程通信,并且需要对 Python 对象进行腌制/取消腌制——同样,这比线程更昂贵。

您需要弄清楚哪种权衡最适合您的目的。

于 2013-02-22T19:11:48.587 回答
2

首先,tl;博士:

concurrent.futures如果您使用的是 3.2+,请使用,或者如果您使用的是 2.x,则使用 PyPI 上向后移植相同内容的模块futures

您可以使用 a 编写代码并将其ThreadPoolExecutor切换为 aProcessPoolExecutor作为单行更改。而且 API 是如此的小而简单,没有什么可混淆的。


还要求命令异步执行操作不是一种选择,因为我希望机器人易于扩展。

我不明白这是怎么回事。异步代码并没有降低其可扩展性。当然,您必须知道如何编写异步代码才能对其进行扩展,但是成千上万的 JS 新手程序员每天都在做几乎可以完成的工作,而 Python 使它变得容易得多(请参阅monocleinlineCallbacksin twistedtulip等) .)。此外,您在描述中明确将这些东西称为“回调”这一事实意味着您已经在考虑这些术语……</p>

如果您确信这实际上是一项要求,那么twisted是不可接受的。但是gevent(和eventlet,等等)可能是——你可以编写看起来完全同步的代码,并且它是异步运行的。

下一个:

您推荐使用哪个模块来并行运行这些回调中的几个,为什么?

你真的需要并行运行它们吗(你可以利用多个内核同时运行多个 CPU 密集型作业),同时运行(长时间运行的作业不会阻塞其他作业),或者两者都不需要(只要随着工作的完成,它们是并行化、交错式还是序列化都无关紧要)?

如果需要并行性,则需要multiprocessing. 真的没有办法解决这个问题。GIL 将阻止您在单个进程中使用多个内核。

如果只需要并发,可以使用threadingmultiprocessing。进程可能意味着在 Windows 和 Unix 之间(甚至有时在 Unix 之间)有更多的开销和/或更多的可移植性问题,并且它有时会迫使您考虑如何传递数据——或者,如果必须的话,共享它。另一方面,通过强迫您考虑传递或共享数据,线程可以更容易地意外创建竞争和其他错误。(有关权衡的更多信息,请参见isedev 的最佳答案。)

如果您都不需要,您可以使用gevent(或类似的东西)threading、、或multiprocessing。您可以像创建数百个线程或进程一样轻松地创建和切换 10000 个绿色线程,而且开销要少得多。但是,一个长时间运行的受 CPU 限制的命令可能会使您的整个系统停止运行。


无论您使用哪一个,您很可能都希望使用一组greenlet、线程或进程,将命令从队列中拉出(而不是为每个命令派生一个新命令,或者构建更复杂的东西)。

虽然multiprocessing内置了这样的东西,threading但没有。(实际上,有一个基于threading- 的线程池——但它在 中multiprocessing,而不是threading。而且它不是公共 API 的一部分。)

中有很多非常酷的东西multiprocessing,如果你需要,一定要使用它。(还有一些第三方库,其中包含更酷的东西,可以使复杂的用例变得更容易,或者做一些multiprocessing不能做的事情。)但如果没有,那就futures简单多了,而且能力用单行更改(甚至在运行时简单地进行)测试具有线程和进程的同一系统非常好。

于 2013-02-22T20:36:26.490 回答