2017-12-03 3 views
0

저는 파이썬을 처음 접했기 때문에 이것이 어떻게 작동해야하는지에 대한 내 전체 개념이 잘못되었습니다 :파이썬에서 병렬 또는 이벤트 구동 함수?

시간 관리를 위해 RFID 리더를 구축하고 있습니다. 예 : 사용자가 RFID 칩으로 로그인 -> 타이머 분마다 Google 스프레드 시트를 계산하고 업데이트합니다. 업데이트 부분은 정상적으로 작동하지만 잠시 시간이 걸립니다. 하지만 나는 RFID 로그인을 항상 확인하고 싶습니다. 어딘가에 나는 Event driven Programming이 내가 원하는 것을 읽었다.

현재 해킹 자체처럼 느껴지는 모든 일을 진실한 루프에서하고 있습니다. RFID 리더가 신호를 보낼 때 어떻게해도 코드를 실행할 수 있습니까? 그런 다음 매분마다 또는 그렇게 평행하게 업데이트 할 시간이 있습니까? 나는 여기서 가장 좋은 연습이 무엇인지 알고 싶다.

+0

RFID 정보를 어떻게 읽습니까? 정보가있을 때만 읽을 수있는 filedescriptor입니까? – syntonym

+0

https://tutorials-raspberrypi.de/raspberry-pi-rfid-rc522-tueroeffner-nfc/ 사용중인 모듈입니다. 죄송합니다. 전체 프로젝트는 파이썬 버전 – Bajt

+0

에서 수행됩니다. – syntonym

답변

1

이벤트를 병렬화하는 것이 일반적으로 쉽지만 병렬 및 이벤트 구동은 기본적으로 직교합니다. 먼저 이벤트를 처리 한 다음 병렬 처리를 처리하겠습니다. 나중에 사용할 경우에만 사용할 수 있습니다.

파이썬에서 "정상적인"제어 흐름은 반복적입니다. 즉, 코드에서 수행해야하는 지침을 정의한 다음 pc에서이 단계를 단계별로 실행합니다. 코드를 구성하는 방법에는 여러 가지가 있습니다 (기능적, 이벤트 중심, 객체 지향적입니다. X 또는 Y 만 수행 할 수있는 절대적인 범주라고 말하고 싶지는 않습니다.). 이벤트는 일반적으로 이벤트를 정의하고이를 처리하는 방법을 의미합니다. 반복적으로 프로그램 할 수없는 이벤트 구동 방식으로 프로그래밍 할 수있는 프로그램은 없습니다.

파이썬은 asyncio 라이브러리가 도입되었을 때 주로 버전 3.4에서 asyncronuos를 지원합니다. 3.5를 사용하면 구문 설탕 awaitasync도 있습니다. 2.7에 있기 때문에 이것은 사용할 수 없습니다. 이름이 trollius 인 asyncio의 백 포트가 있지만 "이벤트 량이 적을 경우"이것은 잔인합니다. 또한 "자신 만의 기본 이벤트 루프"를 다루는 것이 어렵지 않습니다. 물론 asyncio와 trollius는 훨씬 더 많은 작업을 수행하지만 이러한 기능을 사용하지 않을 경우 귀찮은 이유는 무엇입니까?). 당신은 어떻게 든 사건의 처리 방법을 구별하는 방법을 알아야

events = [] 

while waiting_for_events: 
    if events: 
     event = events.pop() 
     handle_event(event) 

:가 발생할 때

기본 워크 플로우를 처리 한 후 이벤트를 기다리고있다. "완전한 기능을 갖춘 이벤트 루프"의 경우 상속 기능이있는 다른 클래스를 사용하지만 각 이벤트에 대해 이름 만 사용할 수 있습니다. 우리는 또한 우리가 만난 RFID와 같은 종류의 data이 필요할 것입니다.

timer = 0 
current_time = time.perf_counter() 

while waiting_for_events: 

    rfid = get_rfids() 
    if rfid: 
     events.append(Event("rfid", rfid)) 

    if timer > 1: 
     events.append(Event("timer", timer)) 
     timer = 0 
    else: 
     timer += time.perf_counter() - current_time 
     current_time = time.perf_counter() 

    if events: 
     event = events.pop() 
     handle_event(event) 

:

def handle_rfid(data): 
    ... 

def handle_timer(data): 
    ... 

event_handler_mapping = {"rfid": handle_rfid, "timer": handle_timer} 

def handle_event(event): 
    event_handler_mapping[event.name](event.data) 
우리는 여전히 이벤트를 생성 할 필요가

, 그래서 이벤트를 얻기 위해 eventloop를 다시 작성할 수 있습니다 :

from collections import namedtuple 
Event = namedtuple("Event", ["name", "data"]) 

그런 다음 우리는 단순히 그들을 처리하는 방법에 이벤트를 매핑해야 그리고 이제 우리는 "사건 중심적"입니다. 좋은 점은 더 많은 이벤트로 쉽게 확장 할 수 있다는 것입니다. 나쁜 것은 여전히 ​​이미 가지고있는 것과 똑같은 일을하지만 더 복잡하다는 것입니다. 또한 이벤트 처리가 많은 시간을 필요로 할 경우 (스프레드 시트를 업데이트하는 경우 인 것처럼 보임) 다른 이벤트는 생성되고 처리되지 않습니다 ( ). 이것은 병렬 처리가 작용한다는 것입니다.

기본적으로 병렬 처리 란 여러 개의 코어를 사용할 수 있음을 의미합니다. 여기서 우리는 실제로 "동시성 (concurrency)"만 필요합니다. 이는 두 가지 일이 동시에 일어날 수 있음을 의미합니다. 이것은 진정한 병렬 처리보다 "더 쉽다", 우리는 단지 다른 것들 사이를 전환 할 수 있지만 모든 것을 순차적으로 수행 할 수있다. 파이썬에서 이것은 기본적으로 다중 처리 (병렬 처리)와 스레드 ("유일한"동시성)로 귀결됩니다 (다른 프로그래밍 언어 스레드는 실제로 병렬 처리를 수행하지만 파이썬에서는이 경우가 아니기를 원합니다). 동시성 문제는 항상 syncronisation입니다. 같은 일이 일어날 수있는 경우, 두 개의 스레드가 동일한 변수를 변경하려고하면 나쁜 일이 발생할 수 있습니다. 일반적으로 스레드간에 공유되는 변수에 액세스하는 데 thread-safe 함수 만 사용한다면 안전합니다.

파이썬 스레드는 threading 모듈에서 생성됩니다. 다른 곳의 스레드를 이미 알지 못한다면 개인적으로 이해하기가 어렵지만 요점은 다음과 같습니다. 스레드에서 함수를 실행하려면 threading.Thread(target=function)을 사용하고 thread.start()을 사용하십시오. 당신이 _update_spreadsheet 내에서 변수에 액세스 할 경우에만 스레드 안전 기능을 사용하려면 carefule 할 필요가

def run_in_thread(f, *args, **kwargs): 
    thread = Thread(target=f, args=args, kwargs=kwargs) 
    thread.start() 

def _update_spreadsheet(data): 
    # logic here 

# when using the event driven approach from above 
def handle_timer(data): 
    run_in_thread(_update_spreadsheet(data)) 

참고 : 다음을 사용할 수 있습니다. 가능한 한 작은 스레드 간 통신으로 사용하는 것이 "최상"입니다. queue은 종종 좋은 선택입니다.

이벤트 기반 조직이 없으면 병렬 처리/동시성을 사용할 수 있습니다. 이미 코드를 이벤트 처리기로 나누었 기 때문에 별도의 스레드에서 장시간 실행되는 이벤트 처리기를 호출 할 수 있습니다.

스레드와 스레드가 모두 오버 헤드를 가지고 있기 때문에 스레드와 관련된 모든 이벤트 및 이벤트 처리기를 사용하는 것은 좋지 않습니다. 따라서 asyncio (및 다른 모든 이벤트 루프)는 "적어도 하나의 이벤트를 처리 할 수있을 때까지 대기"를 구현합니다. 이것은 "오랜 시간"이 필요하기 때문에 인터넷 입력 및 출력에서 ​​가장 흥미 롭습니다. 종종 select과 같은 것을 사용합니다. 다른 이벤트 (타이머, 디스크에서 읽기, 일부 하드웨어 이벤트 대기, ...)는 "무언가 일어날 때 나를 깨우기"위한 다른 메커니즘이 필요합니다. 이 모든 것을 통합하는 것은 당신을위한 asyncio 기능 중 하나입니다.

+0

와우, 상세한 답변을 해주셔서 너무 감사드립니다! 저는 현재 일하고 있으며 이번 주말에 그것을 점검 할 것입니다. 그러나 그것은 저를 위해 많은 질문을 정리했습니다. – Bajt

관련 문제