2016-10-12 2 views
3

나는 일반적으로 스레딩에 익숙하지 않고 여러 가지 아이디어로 내 밑에 발을 들여 놓았다. 그러나, 나는 설명 할 방법이 확실하지 않은 것을 발견했습니다.이상한 출력 오류가있는 파이썬 스레딩

import threading, datetime 
class ThreadClass(threading.Thread): 
    def run(self): 
     for _ in range(3): 
      now = datetime.datetime.now() 
      print "%s: %s" %(self.getName(), now) 

for i in range(2): 
    t = ThreadClass() 
    t.start() 

이 프로그램은 내가하고 싶었던 정확히 않습니다, 그러나, 출력이 거기에 어떤 임의의 오류가 있습니다 : 여기에 코드입니다.

Thread-1: 2016-10-12 17:34:23.012462 
Thread-1: 2016-10-12 17:34:23.012802 
Thread-2: 2016-10-12 17:34:23.013025 
Thread-2: 2016-10-12 17:34:23.013108 

Thread-2: 2016-10-12 17:34:23.013225 
Thread-1: 2016-10-12 17:34:23.013252 

오류는 상대적으로 일관됩니다 (즉, 동일한 공간과 새 행이 다른 장소에 출력 됨). 나는 그것이 같은 시간에 출력 스트림에 쓰려고하는 스레드와 관련이 있다고 의심하지만,이 특정 실행에서는 Thread-2가 실행 중일 때 두 가지 오류가 발생합니다.

이 문제가 발생하는 이유에 대한 설명이 있으면 감사드립니다.

나는이 코드를 우분투 14.04 (듀얼 코어 CPU)에서 파이썬 2.7로 실행하고있다.

답변

1

귀하의 질문 중 일부는 입니다. 왜이 발생합니까? 그리고 당신은 당신의 출력에 알 수 있습니다로서의 좋은 질문은 완전히 가짜 공간도 스레드의 실제로 어떻게 그 거기 않았다

Thread-1: 2016-10-12 17:34:23.012802 
Thread-2: 2016-10-12 17:34:23.013025 
^ 

를 인쇄하려고하는 것이 무엇입니까? 귀하의 스레드 중 하나도 인쇄를 시도하지 않았습니다! Python 2.x의 print 문이 부드러운 간격 인 을 구현하는 방식 때문입니다.

예를 들어 ...당신이 print 1,을 실행할 때의 최종 출력을 제공하기 위해 삽입 할 공간의 원인이됩니다 다음 stdout

1    # there is no space after that 1 yet! 

후속 print 2에 나타납니다

1 2 

어떤 일이 일어나고 것은 print <something>, 문이 컴파일됩니다 있다는 것입니다 바이트 코드 연산 PRINT_ITEM. PRINT_ITEM의 구현이 스트림의 마지막 PRINT_ITEM 인쇄 소프트 공간을 필요로 표시된 경우

  • 검사 출력 스트림을 참조하는 단계;
  • 만약 그렇다면 "";
  • 다음 우리 항목을 인쇄하고 다른 부드러운 공간이 필요하다고 스트림을 언급하십시오.

또 다른 바이트 코드 작업 PRINT_NEWLINE이 새로운 행을 인쇄하고 스트림의 소프트 공간 마커를 지 웁니다.

는 따라서
PRINT_ITEM   # print the top of the stack 
PRINT_NEWLINE  # print a new line 

, 스레드 상호 작용을 의미 할 수 있습니다 :

print "%s: %s" %(self.getName(), now) 

이가로 컴파일됩니다 :

  • Thread-1 코드에서 이제

    각 스레드는 다음을 수행합니다 PRINT_ITEM을 수행하고 스트림을 다음에 대한 소프트 스페이스가 필요하다고 표시합니다 PRINT_ITEM;

  • Thread-2PRINT_ITEM으로 시작할 수 있으며 스트림에는 부드러운 공간이 필요합니다.
  • Thread-1 이제 새 줄이 인쇄됩니다.
  • Thread-2 이제 해당 공간과 해당 항목이 인쇄됩니다. 경우이 오류가 발생하지 않을 것이라고

참고 : 당신이 당신의 출력을 수행하는 sys.stdout.write을 사용

  • ; 또는
  • 당신은 다른 IO 구조를
+0

네, 내가 찾고있는 해답의 이상을 가지고 파이썬 3.x를을 사용했다. 출력 스트림이 호출되는 방식 또는 인쇄 할 항목을 여러 개받을 때 수행해야하는 방식이 있어야한다고 생각했습니다. 설명 주셔서 감사합니다! – BrandonM

1
당신은 logging 모듈을 찾고

:

15.7.9합니다. 스레드 안전

로깅 모듈은 클라이언트에서 수행해야 할 특별한 작업없이 스레드로부터 안전하도록 만들어졌습니다. 스레딩 잠금을 사용하여이 작업을 수행합니다. 모듈의 공유 데이터에 대한 액세스를 직렬화하는 하나의 잠금이 있으며 각 핸들러는 기본 I/O에 대한 액세스를 직렬화하는 잠금을 작성합니다. 여기

은 예입니다 세마포어

from threading import Semaphore 
writeLock = Semaphore(value = 1) 

...

요셉의 답장
FORMAT = '%(threadName)s %(asctime)s' 
logging.basicConfig(format=FORMAT, level=logging.DEBUG) # "level" default is to only print WARN and above. 
logger = logging.getLogger('MyThreadClass') 
logger.debug('') 
2

보완, 당신이 사용할 수있는

당신이 스레드에서 인쇄하려고

:

writeLock.acquire() 
print ("%s: %s" %(self.getName(), now)) 
writeLock.release() 

writeLock은 release()까지 한 번에 하나의 스레드 만 인쇄 할 수 있도록합니다.

이미지 "파리의 제왕"의 외뿔대와 같은 세마포어는 말할 수 있습니다. 첫 번째 연사가 끝나면 그는 다음 연사에게 넘깁니다.