在Linux机器上(Debian wheezy),我正在尝试编写一个基于事件的服务器,它执行以下操作:
抓取input设备(一个特殊的键盘)的独占input,以防止击键进入通常的事件链。
在扭曲的反应堆中注册事件
在等待事件返回时注册callback。 这个callback会在收到一个特殊的密钥序列后发送一个HTTP请求。
这是来自pyevdev
包的示例代码。 它的作品,我得到通知,并接受相应的击键。
通过查看read_loop()
命令的源代码,它也使用类似于twisted的select
语句。
我的问题
我怎样才能将这段代码集成到python Twisted? 一个想法是查看底层的字符设备/dev/input/event0
并以非阻塞的方式读取它。 如果如果是一个普通的文件,我会用inotify的东西,但在这种情况下,我不知道。
来自evdev包的示例代码
from evdev import InputDevice, categorize, ecodes, list_devices devices = [InputDevice(fn) for fn in list_devices()] for dev in devices: print(dev.fn, dev.name, dev.phys) dev = InputDevice('/dev/input/event0') # get exclusive access to input device dev.grab() for event in dev.read_loop(): if event.type == ecodes.EV_KEY: print categorize(event)
evdev.device.InputDevice
有一个fileno()
方法 ,这意味着你可以把它连接到一个Twisted IReactorFDSet
; 在evdev
相关的Linux上几乎所有可用的反应器都实现这个接口。 由于事件设备是一个带有文件描述符的对象,你可以直接读取,所以你需要一个IReadDescriptor
来包装它。
与您的示例大致相同的逻辑实现,但使用reactor来处理事件,可能如下所示:
from zope.interface import implementer from twisted.internet.interfaces import IReadDescriptor @implementer(IReadDescriptor) class InputDescriptor(object): def __init__(self, reactor, inputDevice, eventReceiver): self._reactor = reactor self._dev = inputDevice self._receiver = eventReceiver def fileno(self): return self._dev.fileno() def logPrefix(self): return "Input Device: " + repr(self._dev) def doRead(self): evt = self._dev.read_one() try: self._receiver.eventReceived(evt) finally: pass def connectionLost(self, reason): self.stop() self._receiver.connectionLost(reason) def start(self): self._dev.grab() self._reactor.addReader(self) def stop(self): self._reactor.removeReader(self) self._dev.ungrab() from evdev import InputDevice, categorize, ecodes, list_devices devices = [InputDevice(fn) for fn in list_devices()] for dev in devices: print(dev.fn, dev.name, dev.phys) dev = InputDevice('/dev/input/event0') class KeyReceiver(object): def eventReceived(self, event): if event.type == ecodes.EV_KEY: print(categorize(event)) def connectionLost(self, reason): print("Event device lost!!", reason) from twisted.internet import reactor InputDescriptor(reactor, dev, KeyReceiver()).start() reactor.run()
请注意,这段代码是完全没有经过测试的,所以它起初可能不太合适,但至少应该给你一个什么是必需的概念。