(내 의견에 대하여 ..) asyncio
조금 가벼운 무게이지만, threading
또한 시스템을 호출하는 이벤트를 가지고 있으며, 현재 더 나은 (스레딩 asyncio보다 더 오래되고와있다 문서화 조금 조금 덜 추상적입니다.) 내가 이해할 때, 당신은 다른 작업을하면서 블로킹 리소스를 읽을 수 있기를 원합니다. 이 경우 텍스트 파일을 표준 출력으로 천천히 인쇄하면서 카드를 읽을 때까지 대기 할 스레드를 생성합니다. 이것은 그런 식으로하는 방법의 예일뿐입니다. 비슷한 결과를 얻는 방법은 여러 가지가 있습니다.
import binascii
import time
import threading
from collections import deque #use as a fifo queue
queue = deque() #queue to pass information from thread to main process
queue_lock = threading.Lock() #prevent possible issues from
txt_file = '50_shades_of_grey.txt' #don't ask ;)
running = True
def nfc_reader():
#copied from adafruit example
import Adafruit_PN532 as PN532
CS = 18
MOSI = 23
MISO = 24
SCLK = 25
pn532 = PN532.PN532(cs=CS, sclk=SCLK, mosi=MOSI, miso=MISO)
pn532.begin()
ic, ver, rev, support = pn532.get_firmware_version()
print(f'Found PN532 with firmware version: {ver}.{rev}')
pn532.SAM_configuration()
# Main loop to detect cards and read a block.
print('Waiting for MiFare card...')
while True:
if not running: #cheap way to kill a thread nicely (cheap ain't pretty)
return
#don't bother specifying a timeout, they forgot to support it in the library
uid = pn532.read_passive_target()
# Try again if no card is available.
if uid is None:
continue
print('Found card with UID: 0x{0}'.format(binascii.hexlify(uid)))
# Authenticate block 4 for reading with default key (0xFFFFFFFFFFFF).
if not pn532.mifare_classic_authenticate_block(uid, 4, PN532.MIFARE_CMD_AUTH_B,
[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]):
print('Failed to authenticate block 4!')
continue
# Read block 4 data.
data = pn532.mifare_classic_read_block(4)
if data is None:
print('Failed to read block 4!')
continue
# make sure our queue is free
with queue_lock:
# replaced print with deque.append
queue.append(f'Read block 4: 0x{binascii.hexlify(data[:4])}')
#optionally emit some sort of signal that data is ready. In our case the main loop will chech periodically on it's own
# Main program
nfc_thread = threading.Thread(target=nfc_reader)
nfc_thread.start()
with open(txt_file, 'r') as f:
while True: #also cheap, but easy
if queue: #bool(deque) works like bool(list)
with queue_lock:
print("we found a card!")
print(queue.popleft())
continue
try:
print(next(f)) #otherwise go back to more interesting matters
except StopIteration:
running = False
nfc_thread.join()
break
time.sleep(.9) #notice loop time will be less than timeout on nfc read.
# you could put the printing of the *book* into another thread
# and use events to immediately call your return from your
# nfc reader
@Aaron의 답변에 따라 해봤 코드입니다. 파이썬 3.x의 asyncio 모듈은 기본적인 이벤트 핸들러 클래스를 내장하고 있습니다. https://docs.python.org/3/library/asyncio-eventloop.html – Aaron
궁극적으로 이벤트를 기다리기 위해서는 무엇인가가 블로킹되어야하며, 이벤트 핸들러 해당 이벤트를 올바른 콜백 함수로 보내 처리합니다. 콜백이 즉시 반환되는 한 아무런 문제가 없습니다. API에서 솔루션을 함께 패치해야하는 경우 변경할 수 없거나 변경하고 싶지 않습니다. 스레드 내에서 블로킹 호출을 넣고 스레드가 값을 업데이트하고 콜백이 해당 값을 폴링합니다 (잠금 장치와 원하는 안전성 요소 포함). – Aaron
흥미롭게도 adafruit 라이브러리의 timeout 키워드는 무시됩니다. – Aaron