一个干净,轻量级的替代Python的扭曲?

时间:2009-12-01 06:49:32

标签: python networking twisted asynchronous

A(很久)以前我写了一个网络蜘蛛,我多线程,以便同时发生并发请求。那是在我的Python青年时代,在我知道GIL以及它为多线程代码创建的相关问题之前的几天(IE,大多数时候东西最终被序列化了!)......

我想重做这段代码,使其更强大,性能更好。我基本上有两种方法可以做到这一点:我可以在2.6+中使用新的multiprocessing module,或者我可以选择某种类型的基于反应器/事件的模型。我宁愿做更晚的事情,因为它更简单,更不容易出错。

因此问题涉及哪种框架最适合我的需求。以下是我目前了解的选项列表:

  • Twisted:Python反应器框架的祖先:看起来很复杂但有点臃肿。小任务的陡峭学习曲线。
  • Eventlet:来自lindenlab的人。基于Greenlet的框架,适用于这些类型的任务。我看了一下代码,但它并不太漂亮:非pep8兼容,分散打印(为什么人们在框架中执行此操作!?),API似乎有些不一致。
  • PyEv:不成熟,现在似乎不是任何人使用它虽然它基于libevent所以它有一个坚实的后端。
  • asyncore:从stdlib:über低级别来看,似乎只是为了让一些事情发生而需要做很多工作。
  • tornado:虽然这是面向服务器的产品,专为服务器动态网站而设计,但它的确具有async HTTP client和简单ioloop。看起来它可以完成工作但不是它的目的。 [编辑:不幸的是不能在Windows上运行,这对我来说很重要 - 这是我支持这个蹩脚平台的要求]

我有什么遗漏吗?当然必须有一个适合简化的异步网络库的最佳点的库!

[编辑:非常感谢intgr指向this page的指针。如果你滚动到底部,你会看到有一个非常好的项目列表,旨在以某种方式解决这个任务。事实上,自Twisted开始以来,事情确实已经发生了变化:人们现在似乎更倾向于基于co-routine的解决方案而不是传统的反应堆/回调导向解决方案。这种方法的好处是更直接的代码更清晰:我在过去肯定发现过,特别是在C ++中使用boost.asio时,基于回调的代码可能会导致设计难以理解并且相对较少对未经训练的眼睛模糊不清。使用协同例程允许您编写至少看起来更加同步的代码。我想我现在的任务是找出我喜欢的这些库中的哪一个,并试一试!很高兴我现在问...]

[编辑:对于任何跟随或偶然发现这个问题的人或者在任何意义上关心这个话题的人都可能感兴趣:我找到了一份非常好的关于这份工作的the available tools状态的文章]

14 个答案:

答案 0 :(得分:97)

扭曲是复杂的,你是对的。 Twisted是膨胀。

如果你看看这里:http://twistedmatrix.com/trac/browser/trunk/twisted你会找到一个有组织,全面且经过良好测试的互联网许多协议套件,以及要编写的帮助代码并部署非常复杂的网络应用程序我不会把膨胀与全面性混为一谈。

众所周知,Twisted文档从初看起并不是最方便用户的,我相信这会让一些不幸的人失望。但如果你投入时间,扭曲是惊人的(恕我直言)。我做了,它证明是值得的,我建议其他人尝试相同的。

答案 1 :(得分:56)

geventeventlet cleaned up

API-wise遵循与标准库(特别是线程和多处理模块)相同的约定。因此,您需要熟悉QueueEvent等常用内容。

它仅支持libevent更新: libev since 1.0)作为reactor实现,但充分利用它,具有基于libevent-http和解析DNS的快速WSGI服务器通过libevent-dns进行查询,而不是像大多数其他库一样使用线程池。 (更新:,因为1.0 c-ares用于进行异步DNS查询;线程池也是一种选择。)

与eventlet类似,它使用greenlets使回调和延迟变得不必要。

查看示例:concurrent download of multiple urlslong polling webchat

答案 2 :(得分:27)

我喜欢concurrence Python模块,它依赖于Stackless Python微线程或Greenlets来实现轻量级线程。所有阻塞网络I / O都通过单个libevent循环透明地异步,因此它应该与真正的异步服务器一样高效。

我认为这种方式类似于Eventlet。

缺点是它的API与Python的sockets / threading模块完全不同;你需要重写你的应用程序(或编写兼容性填充层)

编辑:似乎还有cogen,它类似,但使用Python 2.5的增强型生成器作为其协程,而不是Greenlets。这使得它比并发和其他替代方案更便携。网络I / O直接使用epoll / kqueue / iocp完成。

答案 3 :(得分:27)

NicholasPiël在他的博客上编写了一个真正interesting comparison的此类框架:非常值得一读!

答案 4 :(得分:15)

这些解决方案都不会避免GIL阻止CPU并行性这一事实 - 它们只是获得线程已经拥有的IO并行性的更好方法。如果你认为你可以做得更好IO,那么一定要追求其中之一,但如果你的瓶颈在于处理结果,除了多处理模块之外,这里的任何事都没有用。

答案 5 :(得分:11)

我不会打电话给Twisted臃肿,但很难绕开你的脑袋。我避免真正解决了一段时间的学习问题,因为我总是希望“小任务”更容易一些。

然而,现在我已经使用了它,我不得不说包含所有电池非常好。

我所使用的所有其他异步库最终都不像它们出现的那样成熟。 Twisted的事件循环是可靠的。

我不太确定如何解决陡峭的扭曲学习曲线。如果有人将它分叉并清理一些东西,比如删除所有向后兼容性和死亡项目,这可能会有所帮助。但我认为这就是成熟软件的本质。

答案 6 :(得分:8)

Kamaelia尚未被提及。它的并发模型基于将组件连接在一起,并在收件箱和发件箱之间传递消息。 Here是一个简短的概述。

答案 7 :(得分:7)

答案 8 :(得分:4)

有一本关于这个主题的好书:Abe Fettig撰写的“Twisted Network Programming Essentials”。这些例子展示了如何编写非常Pythonic代码,对我个人而言,不要基于臃肿的框架打击我。看看书中的解决方案,如果它们不干净,那么我不知道干净意味着什么。

我唯一的谜是和其他框架一样,比如Ruby。我担心,它会扩大规模吗?我不想将客户端提交到一个会出现可伸缩性问题的框架。

答案 9 :(得分:4)

Whizzer是一个使用pyev的小型异步套接字框架。它非常快,主要是因为pyev。它试图提供一个类似的界面,扭曲了一些细微的变化。

答案 10 :(得分:2)

同时尝试Syncless。它是基于协程的(所以它类似于Concurrence,Eventlet和gevent)。它实现了socket.socket,socket.gethostbyname(等),ssl.SSLSocket,time.sleep和select.select的drop-in非阻塞替换。它很快。它需要Stackless Python和libevent。它包含一个用C(Pyrex / Cython)编写的强制Python扩展。

答案 11 :(得分:2)

我确认无同步的优点。它可以使用libev(libevent的更新,更清晰和更好的性能版本)。很久以前它没有libevent那么多的支持,但现在开发过程更进一步,非常有用。

答案 12 :(得分:1)

如果您只想要一个简化的轻量级HTTP请求库,那么我会发现Unirest非常好

答案 13 :(得分:0)

欢迎您查看PyWorks,它采用了一种完全不同的方法。它允许对象实例在自己的线程中运行,并对该对象进行函数调用异步。

让一个类继承自Task而不是object,它是异步的,所有方法调用都是Proxies。返回值(如果需要)是Future proxies。

res = obj.method( args )
# code continues here without waiting for method to finish
do_something_else( )
print "Result = %d" % res # Code will block here, if res not calculated yet

PyWorks可以在http://bitbucket.org/raindog/pyworks

找到