2010-02-26 3 views
4

이것이 간단한 문제 일 것입니다.하지만 당황 스럽습니다.Python의 time.sleep - 절대로 깨우지 마십시오

[] 중지 보도 : 나 옳았다. 해결책이 발견되었습니다. 답변을 참조하십시오.]

저는 멀티 스레드 응용 프로그램을 테스트하기 위해 Python의 unittest 프레임 워크를 사용하고 있습니다. 멋지고 똑바로 - 공통 큐를 모니터링하는 5 또는 그 이상의 작업자 스레드와 단일 작업자 스레드가 작업 항목을 만들고 있습니다. 생성자 스레드가 테스트 케이스에 의해 트리거됩니다.

이 테스트에서는 하나의 작업 만 대기열에 넣습니다. 테스트에서 수행하는 처리는 실제 처리를위한 스텁 일 뿐이므로 작업자 스레드는 작업이 실제로 완료되기 전에 경과 된 시간을 시뮬레이션하기 위해 5 초 슬립을 수행하고 스레드는 다른 작업을 수행 할 준비가됩니다 . 코드의 조각으로

입니다 : 이제

logging.info("Sleep starting") 
time.sleep(5) 
logging.info("Waking up") 

이상한 부분. "잠자기 시작"로그 메시지가 표시되지만 깨우기 메시지는 표시되지 않습니다. 프로그램이 잠기고 키보드 인터럽트 (Ctrl + C)에 응답하지 않습니다. CPU로드가 매우 낮습니다.

Windows 및 Ubuntu (Python 2.6.2)에서 같은 문제가 발생합니다.

예외가 발생하여 숨겨져 있기 때문에 나는 첫 번째 줄과 두 번째 줄 사이에 "print 1/0"을 추가합니다. 제로에 의한 나누기 오류가 발생하는 것을 봅니다. 나는 잠을 자고 그것을 옮기고 나는 그 메시지를 결코 보지 못한다.

나는 "다른 스레드가 동시에 매우 큰 데이터를 기록하려고 시도하고 있으며 여전히 버퍼링 중입니다. 무엇을하고 있습니까?"라고 생각했습니다.

글쎄, 이번에는 테스트가 unittest로 돌아 왔는데, 여기서 unittest는 시스템 상태를 테스트하기 전에 스레드가 시작될 때까지 기다리는 동안 일시 중지됩니다.

logging.info("Test sleep starting") 
time.sleep(0.25) 
logging.info("Test waking up") 

와우. 그것은 정확히 같은 방식으로 얼어 있습니다! 첫 번째 로그 메시지가 나타나고 두 번째 로그 메시지가 표시되지 않습니다.

나는 최근에 내가 "아무 것도 만지지 않았다"고 주장 할 수 없도록 크게 재 작성했으며 변경 사항이 부적절하다는 것을 알지 못합니다.

의심스러운 지역 :. 내가 threading.Lock과 (나는 GIL의 안전을 추론하는 방법을 모른다, 그래서 내가 무엇을 알고에 충실하기 때문에 내가 대해 아무것도 "deadlocky"를 볼 사용을 포함하고

  • 내 코드.

  • 내가 파이썬의 유닛 테스트 프레임 워크에 새로운 오전이.이 로깅 또는 이러한 증상을 시뮬레이션 할 수있는 그와 유사한 리디렉션와는 않습니다 뭔가? 아니, 비 - 표준 시간 모듈을 교체하지 않은

  • !

스레드가 깨어나지 않게하려면 어떻게해야합니까? 내가 또 놓친 게 있니?

+0

아마도 sleep (초)을 사용하십시오. (시간 가져 오기 잠에서) 저는 python 사용자가 아닙니다. 단지 google을 사용하여 time.sleep (sec) 명령이 5 초만 머물지 않고 전체 프로그램을 정지시킬 수 있다고 상상할 수 없습니다. 어쩌면 다른 곳에 문제가 있습니까? 다른 스레드 또는 뭔가 .. – TheChange

+0

@TheChange. 나는 똑같은 기능을 사용하고있다. 그냥 사소한 네임 스페이스 차이. 나는 time.sleep()이 완전한 프로그램 (또는 최소한 두 개의 스레드)을 동결시킬 수 있다고 믿기 어렵다. 그래서 내가 어디에서 찾아야하는지에 대한 힌트를 묻고있다. – Oddthinking

+0

두 가지 제안 : 더미 함수에 monkey-patch'time.sleep' 또는 간단한 print를하는 monkey-patch'logging.info'. 둘 중 하나를 시도해보고 행동에 도움이되는 변화가 있는지 확인하십시오. 또한 CPU를 모니터링하는 동안 Ctrl-C (자동 반복)를 누른 상태에서 그 프로세스의 활동을 모두 감지 할 수 있는지 확인하십시오. 이는 실제로 살아 있다고 제안하지만 뭔가가 신호를 삼키는 것입니다. –

답변

5

한숨.

작업자 스레드 # 1이 (가) 잠자고 잠에서 깨어났습니다. 그런 다음 웨이크 메시지를 기록하고 차단됩니다. 한 번에 하나의 스레드 만 로깅 할 수 있습니다.

UnitTest 실이 자고 나면 잠에서 깨어납니다. 그런 다음 웨이크 메시지를 기록하고 차단됩니다. 한 번에 하나의 스레드 만 로깅 할 수 있습니다.

Worker-Thread-Not-In-The-Question # 2는 대기열의 이전 항목 처리를 조용히 마치고 첫 번째 작업자 스레드가 잠자기 상태였습니다. 그것은 성명서에 도착했습니다. 매개 변수 중 하나가 객체이고 str()이 암시 적으로 호출되었습니다. 해당 개체에 str() 함수에 버그가있었습니다. 데이터 멤버 중 일부에 액세스 할 때 교착 상태가 발생했습니다. 교착 상태가 로깅 기능에 의해 처리되는 동안 발생하여 로깅 스레드 잠금을 유지하고 다른 스레드가 절대로 깨어나지 않게 만드는 것처럼 보입니다.

0으로 나누기 테스트는 결과가 로그하려고했기 때문에 차이가 나지 않았습니다.

+1

분명히 이런 일이 벌어지고있는 것은 정확히 알지 못했지만 로깅 패키지 (락킹 물건과 같은)의 변덕스러운 점 때문에 필자는 필자가'print'로 테스트를 제안했기 때문에 필자를 종종 망쳤습니다. 당신이 그것을 발견 했다니 기쁘다! :) –

+0

https://twitter.com/#!/nedbat/status/194452404794691584 –

+0

@Tim :-) 하! Ned Batchelder의 트위터 피드에서이를 보았습니다. "그는 내 * 피드를 읽고있었습니다." https://twitter.com/#!/talios/statuses/157760121160744960 – Oddthinking

-3

Linux에서는 I/O 스케줄러를 CFQ (Complete Fair Fairing)로 변경해보십시오.

echo cfq > /sys/block/sda/queue/scheduler 
+1

StackOverflow에 오신 것을 환영합니다. 질문을 보면 (a) Windows에서 발생했기 때문에이 Unix 전용 솔루션이 작동하지 않습니다. (b) 문제가 파이썬 쓰레드와 관련되었다는 것; 파이썬에는 OS 레벨 스케줄러의 변경으로 수정되지 않는 자체 스레드 스케줄링이 있습니다. (c) 이미 문제를 발견했으며 교착 상태 였고 스케줄러를 변경해도 수정되지 않습니다. – Oddthinking

관련 문제