🐍

【Python】バーコードリーダーの入力を「キーボード」として奪われないためのevdev活用術

に公開

はじめに

業務効率化の一環として、Raspberry Piと安価なUSBバーコードリーダーを使って、備品管理や在庫管理システムを自作することがあります。

しかし、USBバーコードリーダーの多くは**「USBキーボード(HIDデバイス)」**として認識されるため、以下のような問題に直面しがちです。

  • ターミナルやエディタに、読み取ったコードが勝手に入力されてしまう。
  • SSH接続中や、ディスプレイを繋いでいない(ヘッドレス)環境で、入力をうまくプログラムに渡せない。
  • 複数のリーダーを繋いだときに、どっちが読み取ったか判別できない。

この記事では、Pythonのevdevライブラリを使って、バーコードリーダーの入力をデバイスレベルで直接キャプチャし、他のアプリ(標準入力)に干渉させずにバックグラウンドで処理する方法を解説します。

なぜ標準入力(input())ではダメなのか?

通常、Pythonで入力を受け取るにはinput()を使いますが、これには「フォーカス」が必要です。
しかし、IoTデバイスとして運用する場合、画面がない(ヘッドレス)状態や、別のプログラムが動いている裏でバーコードの読み取りだけを待ち受けたいケースが多々あります。

そこで、Linuxの入力イベントインターフェース(evdev)を直接操作することで、**「特定のデバイスからの入力だけを」「フォーカスに関係なく」**取得します。

Step 1: デバイスの特定

まず、Raspberry Pi(またはLinux PC)にバーコードリーダーを接続し、どのデバイスファイルとして認識されているか確認します。

ls /dev/input/by-id/

以下のような出力が表示されます。
usb-Name_of_Barcode_Reader-event-kbd

このパス(例: /dev/input/event0 のシンボリックリンク)を使用します。

Step 2: evdevのインストール

Pythonからevdevを扱うためのライブラリをインストールします。

pip install evdev

Step 3: 入力を読み取るスクリプトの実装

以下は、特定のデバイスからの入力を監視し、バーコード(数字や文字列)として組み立てるサンプルコードです。

barcode_reader.py
import evdev
from evdev import ecodes, InputDevice, categorize

# デバイスのパスを指定(Step 1で確認したもの)
DEVICE_PATH = '/dev/input/by-id/usb-Your_Barcode_Reader-event-kbd'

# キーコードと文字の対応マップ(簡易版)
scancodes = {
    # 数字キー (キーボードの上段)
    2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8', 10: u'9', 11: u'0',
    # エンターキー
    28: u'ENTER'
}

def read_barcode():
    try:
        device = InputDevice(DEVICE_PATH)
        # grab()することで、このプログラムがデバイスを独占する(他への入力を防ぐ)
        device.grab()
        print(f"Listening on {device.name}...")
        
        barcode = ""
        
        for event in device.read_loop():
            if event.type == ecodes.EV_KEY and event.value == 1: # キーが押された(value=1)時
                key_code = event.code
                
                if key_code in scancodes:
                    char = scancodes[key_code]
                    
                    if char == 'ENTER':
                        print(f"Scanned Code: {barcode}")
                        # ここでDB保存やAPI送信などの処理を行う
                        barcode = "" # リセット
                    else:
                        barcode += char
                        
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # 終了時にデバイスの独占を解放する
        device.ungrab()

if __name__ == '__main__':
    read_barcode()

ポイント解説:device.grab()

このコードの肝は device.grab() です。
これを実行すると、対象のデバイス(バーコードリーダー)からの入力は、このPythonスクリプトだけが受け取るようになります。
これにり、「読み取ったバーコードが誤ってターミナルのコマンドとして実行されてしまった!」という事故を完全に防ぐことができます。

おわりに

evdevを使えば、安価なUSBバーコードリーダーを、業務用の専用入力デバイスのようにスマートに扱うことができます。
Raspberry Piと組み合わせれば、数千円で在庫管理端末や出席管理システムが作れてしまいます。ぜひ試してみてください!


この記事で紹介した内容以外にも、技術情報をブログで発信しています。
MEANTECH
https://meantech.fontfontfont.com/

Discussion