哪个Python异步库最适合我的代码?Asyncore?扭曲?

dav*_*ave 18 python asynchronous twisted asyncore

我有一个我正在研究的程序,它将同时从两个"网络源"读取.我想尝试一种异步方法,而不是使用线程.这让我想知道使用哪个库...

我想出了一些简单的示例代码,它可以演示我的程序将要执行的操作:

import sniffer

def first():
    for station in sniffer.sniff_wifi():
        log(station.mac())

def second():
    for station in sniffer.sniff_ethernet():
        log(station.mac())

first()
second()
Run Code Online (Sandbox Code Playgroud)

这两种sniffer方法看起来有点像这样:

def sniff_wifi(self):

    while True:
        yield mac_address
Run Code Online (Sandbox Code Playgroud)

while True循环显然使得它们阻塞.

我想用asyncore它,因为它是标准库的一部分.没有第三方依赖是奖金.但是,这并不意味着如果你建议我做的话我不会用它...

我可以实现我想用asyncore做的事情吗?如果是这样,你能告诉我如何将我的示例代码转换为'asyncore代码'吗?你知道任何好的asyncore教程吗?

Gly*_*yph 50

扭曲在几乎每种可能的方式都更好.它更便携,功能更强大,更简单,更具可扩展性,维护更好,记录更好,并且可以制作美味的煎蛋卷.无论如何,Asyncore已经过时了.

在一个简短的例子中很难展示Twisted在优秀方面的优势(如何在一个简短的例子中展示一个http/dns/ssh/smtp/pop/imap/irc/xmpp/process-spawning/多线程服务器) ?),所以相反我会关注人们似乎对Twisted最常见的误解之一:它比asyncore更复杂或更难使用.

让我们从asyncore示例开始.为了避免有偏见的演示,我将使用其他人仍然喜欢asyncore的例子.这是一个简单的asyncore示例,摘自理查德琼斯的博客(为简洁而省略了评论).

首先,这是服务器:

import asyncore, socket

class Server(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', port))
        self.listen(1)

    def handle_accept(self):
        socket, address = self.accept()
        print 'Connection by', address
        EchoHandler(socket)

class EchoHandler(asyncore.dispatcher_with_send):
    def handle_read(self):
        self.out_buffer = self.recv(1024)
        if not self.out_buffer:
            self.close()

s = Server('', 5007)
asyncore.loop()
Run Code Online (Sandbox Code Playgroud)

这是客户:

import asyncore, socket

class Client(asyncore.dispatcher_with_send):
    def __init__(self, host, port, message):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        self.out_buffer = message

    def handle_close(self):
        self.close()

    def handle_read(self):
        print 'Received', self.recv(1024)
        self.close()

c = Client('', 5007, 'Hello, world')
asyncore.loop()
Run Code Online (Sandbox Code Playgroud)

有一些模糊的情况,这些代码无法正确处理,但解释它们是无聊和复杂的,代码已经使这个答案足够长.

现在,这里有一些基本相同的代码,使用Twisted.一,服务器:

from twisted.internet import reactor, protocol as p

class Echo(p.Protocol):
    def dataReceived(self, data):
        self.transport.write(data)

class EchoFactory(p.Factory):
    def buildProtocol(self, addr):
        print 'Connection by', addr
        return Echo()

reactor.listenTCP(5007, EchoFactory())
reactor.run()
Run Code Online (Sandbox Code Playgroud)

现在,客户:

from twisted.internet import reactor, protocol as p

class EchoClient(p.Protocol):
    def connectionMade(self):
        self.transport.write(self.factory.data)

    def dataReceived(self, data):
        print 'Received:', data
        self.transport.loseConnection()

class EchoClientFactory(p.ClientFactory):
    protocol = EchoClient
    def __init__(self, data):
        self.data = data

reactor.connectTCP('localhost', 5007, EchoClientFactory('Hello, world'))
reactor.run()
Run Code Online (Sandbox Code Playgroud)

有几件事我想引起你的注意.首先,扭曲的例子缩短了25%,即使对于这个微不足道的事情也是如此.asyncore有40行,Twisted只有30行.随着协议变得越来越复杂,这种差异将变得越来越大,因为您需要为Twisted提供的asyncore编写越来越多的支持代码.

其次,Twisted提供了完整的抽象.使用asyncore示例,您必须使用该socket模块来进行实际的联网; asyncore仅提供多路复用.如果您需要在Windows等平台上进行可移植行为,则会出现此问题.这也意味着asyncore完全缺乏在其他平台上进行异步子进程通信的工具; 你不能将任意文件描述符填充到select()Windows上的调用中.

第三,扭曲的例子是交通中立.没有EchoEchoFactoryEchoClient,EchoClientFactory并且以任何方式特定于TCP.您可以将这些类放入可以通过SSH,SSL或UNIX套接字或管道连接的库中,只需更改底部的一个connectTCP/ listenTCP调用即可.这很重要,因为在协议逻辑中直接支持TLS之类的东西非常棘手.例如,TL​​S中的"写入"将触发较低级别的"读取".因此,您需要将这些问题分开以使其正确.

最后,具体到您的用例,如果您直接处理MAC地址和以太网帧,Twisted包含Twisted Pair,一个用于处理IP和以太网级网络的低级库.这不是Twisted中最积极维护的部分; 代码很旧.但是,它应该有效,如果不成功,我们会认真对待任何错误,并(最终)看到它们得到修复.据我所知,asyncore没有类似的库,它当然不包含任何此类代码.

  • 这将是扭曲作者的精彩介绍. (6认同)
  • 绝对是一个很好的答案,更不用说它来自扭曲的首席架构师...... (4认同)

Nou*_*him 3

Asyncore 很好,但功能不是很丰富,因此当您的应用程序增长时,您可能会遇到问题。话虽这么说,制作原型是很棒的事情。方法非常简单。您定义方法来处理类中的某些事件(何时可以读取,何时可以写入等),然后从 asyncore.dispatcher (我认为)类中对其进行子类化。

模块的官方文档以及 Doug Hellmann关于该模块的优秀 PyMOTW 文章都是查看文档和示例的良好来源。

如果您的协议是会话式的(例如发送这个,接收那个),您可以查看也随标准库一起分发的异步聊天模块以获取想法。

Twisted 是一种更繁重的方法。我相信考虑到它的使用量,它对于更大的项目会更好,但我不能再说什么,因为我没有任何第一手的经验。