「RaspberryPi + ondryaso/pi-rc522 ライブラリで MyFare を操作する」
では、Mifare NFC リーダ/ライタモジュール RFID-RC522 を RaspberryPi / Python3 で使うライブラリとして ondryaso/pi-rc522 を使いました。
大体はうまくいくのですが、時折 E1 とか E2 という文字列が勝手に標準出力されます。python で CUI プログラムを作っていると致命的。
原因
ライブラリのソース中、以下のように特定の条件で無造作に E1 と E2 が print されるようになっています。
.
.
.
if i != 0:
if (self.dev_read(0x06) & 0x1B) == 0x00:
error = False
if n & irq & 0x01:
print("E1")
error = True
if command == self.mode_transrec:
n = self.dev_read(0x0A)
last_bits = self.dev_read(0x0C) & 0x07
if last_bits != 0:
back_length = (n - 1) * 8 + last_bits
else:
back_length = n * 8
if n == 0:
n = 1
if n > self.length:
n = self.length
for i in range(n):
back_data.append(self.dev_read(0x09))
else:
print("E2")
error = True
.
.
.
仕方ないですねえ
ライブラリに手を加える → やめました
上記の print("E1") だとか print("E2") をコメントアウトしたり、print("E1", file=sys.stderr) のようにすれば良い。
そのようにライブラリを書き換えようかな? と思って、インストールしている場所をしらべてみたら・・・
/usr/local/lib/python3.7/dist-packages/pi_rc522-2.2.1-py3.7.egg
にありました。egg形式・・・ ALZip アーカイブ形式かと思いきや、python の setuptools に使われる単なるZipファイルだそうです。
めんどくさそうなので別のやり方で対処することにしました。
redirect_stdout を呼び出し側で使う
ライブラリ呼び出し側の Python プログラム中で対処する方法です。
redirect_stdout を使うと、標準出力を Python プログラム上でリダイレクトすることができます。
Python 3.5 以降で導入されたらしいです。
以下は、https://github.com/ondryaso/pi-rc522/blob/master/README.md から UID を表示する部分を抜粋したものです。
from pirc522 import RFID
rdr = RFID()
f = io.StringIO()
while True:
rdr.wait_for_tag()
(error, tag_type) = rdr.request()
if not error:
print("Tag detected")
(error, uid) = rdr.anticoll()
if not error:
print("UID: " + str(uid))
# Calls GPIO cleanup
rdr.cleanup()
上記を redirect_stdoutを導入して書き直すと以下のようになります。
import io
import os
from contextlib import redirect_stdout
from pirc522 import RFID
rdr = RFID()
f = io.StringIO()
while True:
rdr.wait_for_tag()
with redirect_stdout(f):
(error, tag_type) = rdr.request()
# print(f.getvalue()) # if need print "E1" or "E2"
if not error:
print("Tag detected")
with redirect_stdout(f):
(error, uid) = rdr.anticoll()
# print(f.getvalue()) # if need print "E1" or "E2"
if not error:
print("UID: " + str(uid))
# Calls GPIO cleanup
rdr.cleanup()
上記では E1,E2のエラーをキャプチャーするために、
f = io.StringIO()
としていますが、キャプチャーする必要が無く捨てるだならば
f = open(os.devnull,'w')
とするのでもOKです。
参考
「Pythonで外部ライブラリが標準出力に吐くメッセージを抑制する」
https://qiita.com/zophos/items/2d3aee100eb4f17bd147