2014-03-27 2 views
2

파이썬을 사용하여 마우스 및 키보드 이벤트를 감지하고 감지하는 동안 핫 플러그 ​​작업을 허용하려고합니다. 이 스크립트는 런타임에 키보드와 마우스 플러그인을 자동으로 감지하여 모든 키보드 및 마우스 이벤트를 출력합니다. 필자는이 기능을 실현하기 위해 evdev 및 pyudev 패키지를 사용합니다. 키보드 및 마우스 이벤트 감지 및 플러그인 감지를 비롯하여 대부분 스크립트가 작동합니다. 그러나 마우스를 꽂을 때마다 이상한 일들이 일어나고 스크립트가 제대로 작동하지 않습니다. 여기에 몇 가지 혼란이 있습니다.핫 플러그 ​​이벤트를 감지하는 파이썬 스크립트

(1) 마우스가 시스템에 연결될 때마다 ./mouseX 및 ./eventX를 포함하여/dev/input/folder에 두 개의 파일이 생성됩니다. 나는 두 소스의 결과를보기 위해 고양이를 시도하지만 실제로 차이점이 있지만 Linux가 ./eventX가 이미 존재하더라도 왜 ./mouseX가되는지 이해하지 못한다.

(2) 마우스를 뽑을 때마다 ./mouseX 플러그를 뽑아내는 이벤트가 먼저 발생하는데, evdev에서는 사용하지 않았기 때문에 ./eventX(. 내가 스크립트)가 동시에 분리되었지만 다음 라운드에서 ./eventX 만 검색 할 수있었습니다. 트릭 (내 스크립트에서 변수 i)을 사용하여이 문제를 피할 수 있지만 마우스 장치를 성공적으로 삭제할 수 있지만 키보드에 아무 것도 입력하지 않아도 select.select()는 끝없는 입력 읽기를 시작합니다.

스크립트는 아래에 나열되어 있습니다 (답변에 따라 수정 됨 previous post). 미리 감사드립니다. mouseX는 "전통적인"장치 반면

#!/usr/bin/env python 

import pyudev 
from evdev import InputDevice, list_devices, categorize 
from select import select 

context = pyudev.Context() 
monitor = pyudev.Monitor.from_netlink(context) 
monitor.filter_by(subsystem='input') 
monitor.start() 

devices = map(InputDevice, list_devices()) 
dev_paths = [] 
finalizers = [] 

for dev in devices: 
    if "keyboard" in dev.name.lower(): 
     dev_paths.append(dev.fn) 
    elif "mouse" in dev.name.lower(): 
     dev_paths.append(dev.fn) 

devices = map(InputDevice, dev_paths) 
devices = {dev.fd : dev for dev in devices} 
devices[monitor.fileno()] = monitor 
count = 1 

while True: 
    r, w, x = select(devices, [], []) 

    if monitor.fileno() in r: 
     r.remove(monitor.fileno()) 

     for udev in iter(functools.partial(monitor.poll, 0), None): 
      # we're only interested in devices that have a device node 
      # (e.g. /dev/input/eventX) 
      if not udev.device_node: 
       break 

      # find the device we're interested in and add it to fds 
      for name in (i['NAME'] for i in udev.ancestors if 'NAME' in i): 
       # I used a virtual input device for this test - you 
       # should adapt this to your needs 
       if 'mouse' in name.lower() and 'event' in udev.device_node: 
        if udev.action == 'add': 
         print('Device added: %s' % udev) 
         dev = InputDevice(udev.device_node) 
         devices[dev.fd] = dev 
         break 
        if udev.action == 'remove': 
         print('Device removed: %s' % udev) 
         finalizers.append(udev.device_node) 
         break 


    for path in finalizers: 
     for dev in devices.keys(): 
      if dev != monitor.fileno() and devices[dev].fn == path: 
       print "delete the device from list" 
       del devices[dev] 

    for i in r: 
     if i in devices.keys() and count != 0: 
      count = -1 
      for event in devices[i].read(): 
       count = count + 1 
       print(categorize(event)) 

답변

1
mouseX 및 eventX의 차이는, 일반적으로 말하는

, eventX는 evdev 장치이다 (예를 들어, 다양한 evdev의 IOCTL을 지원하지 않는다.)

게시 한 코드의 문제점을 알 수는 없지만 올바른 일을하는 코드 스 니펫은 여기에 있습니다.

#!/usr/bin/env python 

import pyudev 
import evdev 
import select 
import sys 
import functools 
import errno 

context = pyudev.Context() 
monitor = pyudev.Monitor.from_netlink(context) 
monitor.filter_by(subsystem='input') 
# NB: Start monitoring BEFORE we query evdev initially, so that if 
# there is a plugin after we evdev.list_devices() we'll pick it up 
monitor.start() 

# Modify this predicate function for whatever you want to match against 
def pred(d): 
    return "keyboard" in d.name.lower() or "mouse" in d.name.lower() 

# Populate the "active devices" map, mapping from /dev/input/eventXX to 
# InputDevice 
devices = {} 
for d in map(evdev.InputDevice, evdev.list_devices()): 
    if pred(d): 
     print d 
     devices[d.fn] = d 

# "Special" monitor device 
devices['monitor'] = monitor 

while True: 
    rs, _, _ = select.select(devices.values(), [], []) 
    # Unconditionally ping monitor; if this is spurious this 
    # will no-op because we pass a zero timeout. Note that 
    # it takes some time for udev events to get to us. 
    for udev in iter(functools.partial(monitor.poll, 0), None): 
     if not udev.device_node: break 
     if udev.action == 'add': 
      if udev.device_node not in devices: 
       print "Device added: %s" % udev 
       try: 
        devices[udev.device_node] = evdev.InputDevice(udev.device_node) 
       except IOError, e: 
        # udev reports MORE devices than are accessible from 
        # evdev; a simple way to check is see if the devinfo 
        # ioctl fails 
        if e.errno != errno.ENOTTY: raise 
        pass 
     elif udev.action == 'remove': 
      # NB: This code path isn't exercised very frequently, 
      # because select() will trigger a read immediately when file 
      # descriptor goes away, whereas the udev event takes some 
      # time to propagate to us. 
      if udev.device_node in devices: 
       print "Device removed (udev): %s" % devices[udev.device_node] 
       del devices[udev.device_node] 
    for r in rs: 
     # You can't read from a monitor 
     if r.fileno() == monitor.fileno(): continue 
     if r.fn not in devices: continue 
     # Select will immediately return an fd for read if it will 
     # ENODEV. So be sure to handle that. 
     try: 
      for event in r.read(): 
       pass 
       print evdev.categorize(event) 
     except IOError, e: 
      if e.errno != errno.ENODEV: raise 
      print "Device removed: %s" % r 
      del devices[r.fn] 
관련 문제