2013-05-21 2 views
1

테스트 모듈에 대해 두 개의 스레드 ("test_a"및 "test_b")를 시작하는 주 스레드가있는 경우를 가정 해 봅니다. 테스트 모듈 스레드는 모두 테스트를 수행했는지 또는 오류, 경고가 발생했는지 또는 일부 다른 정보를 업데이트할지 여부를 결정하지 않고 상태를 유지합니다.파이썬에서 스레드 간 통신 (전역 변수를 사용하지 않고)

주 스레드가이 정보에 액세스하여 그에 따라 작동하는 방법. 예를 들어, "test_a"가 오류 플래그를 발생시킨 경우; "main"이 오류가 있기 전에 테스트의 나머지 부분을 알고 중지하는 방법은 무엇입니까?

이 작업을 수행하는 한 가지 방법은 전역 변수를 사용하는 것이지만 매우 추악 해집니다. 아주 빨리.

답변

4

분명한 해결 방법은 생성자/start의 스레드 객체/함수에 전달하여 가변적 인 변수를 공유하는 것입니다.

이를 수행하는 올바른 방법은 적절한 인스턴스 속성을 사용하여 클래스를 작성하는 것입니다. threading.Thread 하위 클래스를 사용하는 경우 스레드 기능 대신 하위 클래스 자체를 해당 속성을 고정 할 장소로 사용할 수 있습니다. 제대로 main_threadtest_a 사이에 동기화 할 수 있도록, 또한 가변 상태 개체로 Lock 또는 Condition

def test_a_func(thread_state): 
    # ... 
    thread_state[0] = my_error_state 
    # ... 

def main_thread(): 
    test_states = [None] 
    test_a = threading.Thread(target=test_a_func, args=(test_a_state,)) 
    test_a.start() 

당신은 (일반적으로 원하는) 할 수 있습니다하지만이 짧은 그냥 때문에 list으로 보여주지 .

(또 다른 옵션은 정보를 전달하는 데 queue.Queue, os.pipe 등을 사용하는 것이지만 여전히 위와 똑같은 방식으로 수행하는 자식 스레드에 대한 큐 또는 파이프를 가져와야합니다.)


그러나 실제로이 작업을 수행해야하는지 고려해 볼 가치가 있습니다. test_atest_b을 "스레드 기능"이 아닌 "작업"으로 생각하면 풀에서 이러한 작업을 실행하고 풀에서 결과 또는 오류를 다시 처리하도록 처리 할 수 ​​있습니다. 예를 들어

다음 test_a 함수는 예외가 발생하는 경우

try: 
    with concurrent.futures.ThreadPoolExecutor(workers=2) as executor: 
     tests = [executor.submit(job) for job in (test_a, test_b)] 
     for test in concurrent.futures.as_completed(tests): 
      result = test.result() 
except Exception as e: 
    # do stuff 

이제, 메인 쓰레드는 예외 및 얻는 것, 즉 with 블록 종료 의미하기 때문에, 다른 모든 작업이 취소됨 던져 버리고 작업자 스레드가 종료됩니다.

2.5-3.1을 사용하는 경우 concurrent.futures이 내장되어 있지 않지만 the backport off PyPI을 설치하거나 multiprocessing.dummy.Pool을 다시 작성할 수 있습니다. (당신은 작업의 시퀀스를 생성해야하고 AsyncResult 객체의 반복자를 다시 얻을 수 map_async 전화 ...하지만 정말 여전히 아주 간단 때문에, 약간 더 복잡 그 방법입니다.)

+0

한'concurrent.futures'. 나는 결코 몰랐다 - 그러나 아마 그들이 3+이기 때문에? – n611x007

+1

@naxa : 3.2 +에서 stdlib에만 있지만, [backport to 2.5+] (https://pypi.python.org/pypi/futures)가 있거나 하위 집합을 만들 수 있습니다 (모든 당신이 필요로하는 부분)을'multiprocessing.ThreadPool' (이것은 2.x에서는 문서화되지 않았지만 항상 존재 함) 위에 꽤 쉽게 구현할 수 있습니다. – abarnert

관련 문제