一起使用gevent和多处理来与子进程通信

时间:2011-02-12 04:02:14

标签: windows asynchronous multiprocessing subprocess gevent

问题:

我可以高效地在Windows上使用多处理模块和gevent吗?

情景:

我有一个基于gevent的Python应用程序在Windows上进行异步I / O.该应用程序主要受I / O限制,但也存在CPU负载较高的峰值。此应用程序需要通过其stdin和stdout控制控制台应用程序。我无法修改此控制台应用程序,用户将能够使用自己的自定义应用程序,只修复基于文本(行)的通信协议。

我有一个使用子进程和线程的工作实现,但我宁愿将整个基于子进程的通信代码与这些线程一起移动到一个单独的进程中,以将主应用程序转回单线程。我打算为此使用多处理模块。

事先阅读:

我一直在网上搜索并阅读一些源代码,所以我知道多处理模块在Windows上使用基于命名管道的Pipe实现。一对multiprocessing.queue.Queue对象将用于与第二个Python进程通信。这些队列基于该管道实现,例如, IPC将通过命名管道完成。

关键问题是,调用传入的Queue的get方法是否会阻止gevent的主循环。这个方法有一个超时,所以我可以把它变成一个带有小超时的循环,但这不是一个好的解决方案,因为它会在很短的时间内阻止gevent,从而损害它的低I / O延迟。

我也愿意接受有关如何规避在Windows上使用管道的整个问题的建议,这已知很难,有时甚至是脆弱的。我不确定在Windows上是否可以使用基于共享内存的IPC。也许我可以用一种允许使用网络套接字与子进程通信的方式来包装控制台应用程序,这已知可以与gevent一起使用。

如果可能,请不要质疑我的主要用例。感谢。

2 个答案:

答案 0 :(得分:1)

Queue的get方法确实是阻塞的。将它与超时一起使用可能会解决您的问题,但它肯定不会是最干净的解决方案,而且最重要的是,它将无缘无故地引入额外的延迟。即使它没有阻塞,这也不是一个好的解决方案。仅仅因为非阻塞本身是不够的,良好的异步调用/ API应该平滑地集成到使用中的I / O框架中。是Python的gevent,C ++的Bovent或C ++的Boost ASIO。

最简单的解决方案是通过生成控制台应用程序并附加到其控制台的入口和出口描述符来使用简单的I / O.有两个主要因素需要考虑:

  • 您的客户可以非常轻松地编写客户端应用程序。他们不必使用任何类型的IPC,套接字或其他代码,这对许多人来说可能是非常困难的事情。使用这种方法,应用程序将只从stdin读取并写入stdout。
  • 使用这种方法测试控制台应用程序非常容易,因为您可以手动启动它们,在控制台中输入文本并查看结果。
  • Gevent非常适合异步读/写。

但是,缺点是您必须启动此应用程序,不支持与其进行并发通信,并且不支持通过网络进行通信。甚至有good example for starters

为了保持简单但更灵活,您可以使用TCP / IP套接字。如果客户端和服务器都在同一台计算机上运行。此外,一个好的操作系统将使用IPC作为底层实现,因此它会很快。而且,如果您担心此案例的性能,您可能根本不应该使用Python并查看其他技术。

即使是幻想解决方案 - 使用ZeroC ICE。它是非常现代的技术,允许几乎无缝的进程间通信。它是一个CORBA杀手,非常容易使用。它被许多人大量使用,被证明是同类产品中最快的并且稳定。这个解决方案的优点在于,您可以无缝地集成多种语言的程序,如Python,Java,C ++等。但这需要您花费一些时间来熟悉一个概念。如果您决定采用这种方式,只需花一天时间阅读文档。

希望它有所帮助。祝你好运!

答案 1 :(得分:0)

你的问题已经很老了。不过,我想建议http://gehrcke.de/gipc - 我相信 - 会以非常直截了当的方式解决所概述的挑战。基本上,它允许您在应用程序的任何位置(也在Windows上)集成基于多处理的子进程。与Process对象的交互(例如调用join())是gevent-cooperative。通过其管道管理,它允许协同阻止进程间通信。但是,在Windows上,IPC目前的效率远低于POSIX兼容系统(因为非阻塞I / O是通过线程池模仿的)。根据应用程序的IPC消息传递量,这可能会也可能不重要。