【发布时间】:2015-03-19 20:20:28
【问题描述】:
(也欢迎帮助以更好的形式形成这个问题)
我正在寻找 twisted 来实现一个与互联网完全无关的异步软件。我还获得了一份令人失望的 Twisted Network Programming Essentials 的副本。它和几乎所有其他教程一样,似乎只将twisted 视为网络客户端,使用内置事件处理程序并静默使用难以概括的内置胶水代码。
对于上下文,我的应用程序希望使用串行/pyserial 与硬件设备通信,并使用 Qt 提供一个 gui。我什至还没有接近开始担心 Qt 反应器(这似乎是一罐蠕虫的另一个承诺)或移植到 Windows 的地步。
首先,我使用了一个扭曲的选择反应器,我在其中添加了一个处理 udev 事件的协议 + 文件描述符。到目前为止我所做的工作,因为 udev 事件触发了协议中的一个函数(eventReceived)。 以下是协议及其添加到反应器的方式:
class UdevMonitorListener(Protocol):
def __init__(self, _reactor=None):
if _reactor is not None:
self._reactor = _reactor
else:
self._reactor = reactor
self.subsystem = 'tty'
self.monitor = None
def startListening(self):
logger.info("Starting UdevMonitorListener")
self.monitor = UdevMonitor(self._reactor, self, self.subsystem)
self.monitor.startReading()
def eventReceived(self, action, device):
if device in connected_devices.udev_ports:
if action == u'remove':
connected_devices.remove_by_udev_port(device)
if action == u'add':
if is_device_supported_from_udev_port(device):
if device not in connected_devices.udev_ports:
connected_devices.append_by_udev_port(device)
def init(_reactor=None):
monitor_protocol = UdevMonitorListener(_reactor)
monitor_protocol.startListening()
函数init() 在reactor.run() 之前由reactor.callWhenRunning() 调用。 eventReceived 函数按 FileDescriptor 的预期调用。如果有帮助,我也可以在此处添加该代码。
我希望 eventRecieved 触发反应器中的某种事件,其他东西可以对其做出反应。该代码不应该关心谁在使用它,该代码也不应该关心谁在生成它。这些事件之间的距离很少,而且我似乎无法找到一个能够干净利落地执行此操作的界面。预计这些事件不会相对罕见地发生,但它们永远不会“结束”。如果要使用 deferred,它必须有某种“刷新”自身的方式来等待下一个事件。处理此类事件的常用模式是什么?
编辑:
为了后代和其他人看,其余的代码:
(来自https://gist.github.com/dpnova/a7830b34e7c465baace7)
class UdevMonitor(FileDescriptor):
"""
File Descriptor for pyudev.Monitor.
@see: U{http://packages.python.org/pyudev/api/monitor.html}.
"""
def __init__(self, _reactor, protocol, subsystem=None):
FileDescriptor.__init__(self, _reactor)
# Set up monitor
context = pyudev.Context()
self.monitor = pyudev.Monitor.from_netlink(context)
if subsystem:
self.monitor.filter_by(subsystem=subsystem)
# Connect protocol
assert isinstance(protocol, UdevMonitorListener)
self.protocol = protocol
self.protocol.makeConnection(self)
def fileno(self):
"""
Return monitor's file descriptor.
"""
return self.monitor.fileno()
def startReading(self):
"""
Start waiting for read availability.
"""
logger.debug("starting udev monitor fd")
self.monitor.start()
FileDescriptor.startReading(self)
def doRead(self):
"""
An event is ready, decode it through Monitor and call our protocol.
"""
logger.debug("udev reports event available")
event = self.monitor.receive_device()
if event:
action, device = event
self.protocol.eventReceived(action, device)
def writeSomeData(self, data):
raise IOError("You can't write to a udev Monitor")
或者包含 connected_devices 和设备搜索的完整模块在 https://gist.github.com/chintal/2511459c02a9767deb5d
【问题讨论】:
-
您可能想要修复您的代码格式。在当前版本的问题中,缩进大多是错误的。