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上的调用中.
第三,扭曲的例子是交通中立.没有Echo和EchoFactory和EchoClient,EchoClientFactory并且以任何方式特定于TCP.您可以将这些类放入可以通过SSH,SSL或UNIX套接字或管道连接的库中,只需更改底部的一个connectTCP/ listenTCP调用即可.这很重要,因为在协议逻辑中直接支持TLS之类的东西非常棘手.例如,TLS中的"写入"将触发较低级别的"读取".因此,您需要将这些问题分开以使其正确.
最后,具体到您的用例,如果您直接处理MAC地址和以太网帧,Twisted包含Twisted Pair,一个用于处理IP和以太网级网络的低级库.这不是Twisted中最积极维护的部分; 代码很旧.但是,它应该有效,如果不成功,我们会认真对待任何错误,并(最终)看到它们得到修复.据我所知,asyncore没有类似的库,它当然不包含任何此类代码.
Asyncore 很好,但功能不是很丰富,因此当您的应用程序增长时,您可能会遇到问题。话虽这么说,制作原型是很棒的事情。方法非常简单。您定义方法来处理类中的某些事件(何时可以读取,何时可以写入等),然后从 asyncore.dispatcher (我认为)类中对其进行子类化。
该模块的官方文档以及 Doug Hellmann关于该模块的优秀 PyMOTW 文章都是查看文档和示例的良好来源。
如果您的协议是会话式的(例如发送这个,接收那个),您可以查看也随标准库一起分发的异步聊天模块以获取想法。
Twisted 是一种更繁重的方法。我相信考虑到它的使用量,它对于更大的项目会更好,但我不能再说什么,因为我没有任何第一手的经验。
| 归档时间: |
|
| 查看次数: |
11182 次 |
| 最近记录: |