我对 Twisted 线程感到困惑。
我听过并读过很多关于 Python 中线程与进程主题的文章、书籍,并且听过一些演示。在我看来,除非要进行大量 IO 操作或想要跨作业利用共享内存,否则正确的选择是使用多处理。
但是,从目前为止我所看到的来看,Twisted 似乎使用了 Threads(来自 python 线程模块的 pThreads)。 Twisted 在处理大量数据方面似乎表现得非常好。
我有相当多的进程,我想在单个节点/服务器上使用 Python 中的 MapReduce 模式将处理分配给它们。他们实际上不做任何 IO,他们只是做很多处理。
Twisted Reactor 是适合这项工作的工具吗?
最佳答案
对您的问题的简短回答:不,扭曲线程不是重型加工的正确解决方案。
如果你有很多处理要做,Twisted 的线程仍然会受到 GIL(全局解释器锁)的约束。无需深入解释,GIL 一次只允许一个线程执行 Python 代码。这实际上意味着您将无法通过单个多线程扭曲进程来利用多个核心。也就是说,一些C 模块(例如 SciPy 的位)可以释放 GIL 并运行多线程,尽管相关的 python 代码仍然有效地是单线程的。
Twisted 的线程主要用于将其与基于阻塞 I/O 的模块一起使用。一个典型的例子是数据库 API,因为 db-api 规范不考虑异步用例,并且大多数数据库模块都遵守该规范。因此,要从扭曲的应用程序中使用 PostgreSQL,必须阻止或使用类似 twisted.enterprise.adbapi
的东西,它是一个使用 twisted.internet.threads.deferToThread< 的包装器
允许在进行其他操作时执行 SQL 查询。这可以允许其他 python 代码运行,因为 socket
模块(以及大多数涉及操作系统 I/O 的其他模块)将在系统调用时释放 GIL。
也就是说,您可以使用twisted 编写一个与许多twisted(或非twisted,如果您愿意)工作人员通信的网络应用程序。然后,每个工作人员都可以处理少量工作,并且您将不会受到 GIL 的限制,因为每个工作人员都是其自己的完全隔离的进程。然后,主进程可以利用twisted 的许多异步原语。例如,您可以使用 DeferredList
等待来自任意数量工作线程的大量结果,然后在所有 Deferred
完成时运行响应处理程序。 (从而允许您进行 map 调用)如果您想沿着这条路线走下去,我建议您查看twisted.protocols.amp
,这是他们的异步消息协议(protocol),并且可以非常简单地用于实现基于网络的 RPC 或 map-reduce。
与多处理
之类的东西相比,运行许多不同的进程的缺点是
- 您失去了简单的流程管理,并且
- 子进程无法像在 UNIX 系统上 fork 一样共享内存。
尽管对于现代系统,2) 很少会成为问题,除非您正在运行数百个子进程。问题1)可以通过使用像supervisord这样的流程管理系统来解决
编辑有关 python 和 GIL 的更多信息,您应该观看 Dave Beazley关于该主题的演讲( website 、 video 、 slides )
关于python - 在单个节点/服务器上使用 Twisted Threading + MapReduce?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5007184/