关闭。此问题不符合 Stack Overflow 准则。它目前不接受答案。我们不允许提出有关书籍、工具、软件库等建议的问题。您可以编辑问题,以便可以用事实和引用来回答它。 7年前关闭。改进这个问题
A(很久以前)我写了一个多线程的网络蜘蛛,以使并发请求能够同时发生。那是在我的 Python 青年时代,在我了解 GIL 及其为多线程代码(IE,大多数时候东西最终都被序列化!)带来的相关问题之前的日子......
我想重新编写此代码以使其更健壮且性能更好。基本上有两种方法可以做到这一点:我可以使用 2.6+ 中的新 multiprocessing module 或者我可以使用某种基于反应器/事件的模型。我宁愿做后者,因为它更简单且不易出错。
因此,问题与哪种框架最适合我的需求有关。以下是我目前所知道的选项列表:
Twisted:Python 反应器框架的鼻祖:看起来很复杂而且有点臃肿。小任务的陡峭学习曲线。
Eventlet:来自 lindenlab 的人。面向此类任务的基于 Greenlet 的框架。不过,我查看了代码,它不太漂亮:不符合 pep8,散布着打印(为什么人们在框架中这样做!?),API 似乎有点不一致。
PyEv:不成熟,现在似乎没有人在使用它,虽然它是基于 libevent 的,所以它有一个可靠的后端。
asyncore:来自 stdlib:über 低级,似乎需要大量的跑腿工作才能使某些东西脱离实际。
tornado:虽然这是一个面向服务器的产品,旨在为动态网站提供服务,但它确实具有异步 HTTP 客户端和简单的 ioloop。看起来它可以完成工作,但不是它的预期目的。 [编辑:不幸的是,它不能在 Windows 上运行,这对我来说很重要——我需要支持这个蹩脚的平台]
有什么我错过的吗?当然,必须有一个适合简化异步网络库的最佳位置的库!
[编辑:非常感谢 intgr 指向 this page。如果您滚动到底部,您会看到一个非常好的项目列表,旨在以一种或另一种方式解决此任务。实际上,自从 Twisted 成立以来,事情似乎确实在发生变化:人们现在似乎更喜欢基于 co-routine 的解决方案,而不是传统的面向反应器/回调的解决方案。这种方法的好处是代码更清晰更直接:我过去确实发现,尤其是在使用 C++ 中的 boost.asio 时,基于回调的代码可能会导致设计难以遵循并且相对晦涩难懂未经训练的眼睛。使用协同例程可以让你编写至少看起来更同步的代码。我想现在我的任务是找出我喜欢这些库中的哪个外观并试一试!很高兴我现在问...]
[编辑:也许任何关注或偶然发现这个问题或在任何意义上关心这个话题的人都会感兴趣:我为这项工作找到了一篇关于 the available tools 当前状态的非常棒的文章]
select
进行 I/O 多路复用。但是您应该能够使用 tornado-pyuv 从中获得不错的性能。 2. Python 3.3+ 和它的 backport trollius 现在有 asyncio,它允许在其事件循环中运行任何 Tornado 应用程序(很快将支持 Twisted)。
Twisted 很复杂,你说得对。 Twisted 不臃肿。
如果您在此处查看:http://twistedmatrix.com/trac/browser/trunk/twisted 您会发现一个有组织、全面且经过良好测试的互联网许多协议套件,以及用于编写和部署非常复杂的网络的帮助代码应用程序。我不会将臃肿与全面性混为一谈。
众所周知,Twisted 文档乍一看并不是最友好的,我相信这会让很多不幸的人望而却步。但是如果你投入时间,Twisted 是惊人的(恕我直言)。我做到了,事实证明这是值得的,我建议其他人也尝试一下。
在 API 方面,它遵循与有意义的标准库(特别是线程和多处理模块)相同的约定。因此,您可以使用熟悉的东西,例如 Queue 和 Event。
它仅支持 libevent (update: libev since 1.0) 作为反应器实现,但充分利用了它,具有基于 libevent-http 的快速 WSGI 服务器并通过 libevent-dns 解析 DNS 查询而不是像大多数其他库一样使用线程池。 (更新: 因为 1.0 c-ares 用于进行异步 DNS 查询;线程池也是一个选项。)
与 eventlet 一样,它通过使用 greenlets 使回调和 Deferred 变得不必要。
查看示例:concurrent download of multiple urls、long polling webchat。
我喜欢 concurrence Python 模块,它依赖于 Stackless Python 微线程或 Greenlets 来实现轻量级线程。所有阻塞网络 I/O 都通过一个 libevent
循环透明地异步化,因此它应该几乎与真正的异步服务器一样高效。
我想它在这种方式上类似于 Eventlet。
缺点是它的 API 与 Python 的 sockets
/threading
模块有很大不同;您需要重写相当多的应用程序(或编写兼容性 shim 层)
编辑:似乎还有 cogen,它是类似的,但它的协程使用 Python 2.5 的增强型生成器,而不是 Greenlets。这使得它比并发和其他替代方案更便携。网络 I/O 直接使用 epoll/kqueue/iocp 完成。
Nicholas Piël 在他的博客上编译了真正interesting comparison的此类框架:非常值得一读!
这些解决方案都不能避免 GIL 阻止 CPU 并行性这一事实——它们只是获得线程已经拥有的 IO 并行性的更好方法。如果你认为你可以做更好的 IO,一定要追求其中之一,但如果你的瓶颈在于处理结果,除了多处理模块之外,这里没有任何帮助。
我不会说 Twisted 臃肿,但很难缠住你的头。很长一段时间以来,我一直避免真正沉迷于学习中,因为我一直希望“小任务”更容易一些。
但是,既然我已经使用它更多了,我不得不说包含所有电池非常好。
我使用过的所有其他异步库最终都没有它们看起来那么成熟。 Twisted 的事件循环是可靠的。
我不太确定如何解决陡峭的 Twisted 学习曲线。如果有人将它分叉并清理一些东西可能会有所帮助,例如删除所有向后兼容的垃圾和死项目。但我猜这就是成熟软件的本质。
PortableGtkReactor
的修复程序吗?
我已经开始在某些事情上使用twisted。它的美丽几乎是因为它“臃肿”。几乎所有主要协议都有连接器。你可以有一个 jabber bot,它会接受命令并发布到 irc 服务器,通过电子邮件将它们发送给某人,运行命令,从 NNTP 服务器读取,并监视网页的更改。坏消息是它可以完成所有这些工作,并且对于像 OP 解释的简单任务而言,它会使事情变得过于复杂。不过,python 的优点是你只包含你需要的东西。因此,虽然下载可能是 20mb,但您可能只包含 2mb 的库(这仍然很多)。我对 twisted 最大的抱怨是,尽管它们包含示例,但除了您自己的基本 tcp 服务器之外的任何内容。
虽然不是 python 解决方案,但我已经看到 node.js 最近获得了更多的吸引力。事实上,我已经考虑过为较小的项目研究它,但当我听到 javascript 时我只是畏缩 :)
关于这个主题有一本好书:Abe Fettig 的“Twisted Network Programming Essentials”。这些示例展示了如何编写非常 Pythonic 的代码,对我个人而言,不要觉得我基于一个臃肿的框架。看书上的解决方案,如果不干净,那我就不知道干净是什么意思了。
我唯一的谜团和其他框架一样,比如 Ruby。我担心,它会扩大吗?我不愿意将客户提交给会出现可伸缩性问题的框架。
也试试 Syncless。它是基于协程的(所以它类似于 Concurrence、Eventlet 和 gevent)。它实现了对 socket.socket、socket.gethostbyname(等)、ssl.SSLSocket、time.sleep 和 select.select 的插入式非阻塞替换。它很快。它需要 Stackless Python 和 libevent。它包含一个用 C (Pyrex/Cython) 编写的强制性 Python 扩展。
我确认 syncless 的优点。它可以使用 libev(更新、更干净、性能更好的 libevent 版本)。前段时间它没有像 libevent 那么多的支持,但现在开发过程更加先进并且syncless
非常有用。
欢迎您查看 PyWorks,它采用了完全不同的方法。它允许对象实例在它们自己的线程中运行,并使对该对象的函数调用异步。
只要让一个类继承自Task而不是object,它是异步的,所有方法调用都是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 上找到
不定期副业成功案例分享