2017-05-19 8 views
1

파이썬의 기본 애플릿에서 코드를 수정하지 않고 테스트하고 문제를 디버깅하도록 만든 코드가 있습니다. 이 날이 코드를 구축 할 수 있습니다Python 스레딩에서 여러 개의 stdout 수행 플러시

#!/usr/bin/env python 
import sys, threading, time 

def loop1(): 
    count = 0 
    while True: 
     sys.stdout.write('\r thread 1: ' + str(count)) 
     sys.stdout.flush() 
     count = count + 1 
     time.sleep(.3) 
     pass 
    pass 

def loop2(): 
    count = 0 
    print "" 
    while True: 
     sys.stdout.write('\r thread 2: ' + str(count)) 
     sys.stdout.flush() 
     count = count + 2 
     time.sleep(.3) 
    pass 

if __name__ == '__main__': 
    try: 
     th = threading.Thread(target=loop1) 
     th.start() 

     th1 = threading.Thread(target=loop2) 
     th1.start() 
     pass 
    except KeyboardInterrupt: 
     print "" 
     pass 
    pass 
이 코드 내 목표는 같은 시간에 (세정과) 표준 출력 형식으로 출력을 표시 이러한 스레드를 모두 가질 수 및 측면에 의해 다음 측면을 가지고있다

또는 뭔가. 문제는 내가 각각 하나씩 씻어 내리기 때문에 기본적으로 다른 문자열을 플러시한다는 것입니다. 나는 이것이 가능하다면 이것이 작동하도록하는 방법을 잘 모른다.

방금 ​​스레드 중 하나를 실행하면 정상적으로 작동합니다. 그러나 터미널 출력에서 ​​동시에 실행되는 자체 문자열로 두 스레드를 모두 실행할 수 있기를 원합니다.

터미널 스크린 샷

당신이 더 많은 정보가 필요하면 알려주세요 : 여기 사진은 내가 갖는 것을 표시한다. 미리 감사드립니다.

+1

인쇄는 스레드로부터 안전하지 않습니다. 'logging' 모듈을 사용하거나, 어떤 종류의 잠금을 구현하거나, 인쇄를 다른 스레드로 옮기십시오. – Blender

+0

나는 그것이 (exaple을 위해) 숫자를 보여줄 것이고 그때 그것을 플러시하고 그것의 오래된 장소에 새로운 것을 프린트하는 것을 좋아하기 때문에 나는 stdout을 사용한다. 따라서 출력 대신에 출력을위한 고정 된 지점을 생성하는 것만으로 모든 번호에 대해 새로운 행을 만들어서 인쇄 할 수 있습니다. – BlackVikingPro

답변

0

각 스레드를 표준 출력으로 출력하는 대신 하나의 스레드가 stdout을 독점적으로 제어하도록하는 것이 더 좋은 해결책입니다. 그런 다음 출력 할 데이터를 디스패치하기 위해 다른 스레드에 대한 스레드 안전 채널을 제공하십시오.

이 작업을 수행하는 좋은 방법은 모든 스레드간에 Queue을 공유하는 것입니다. 큐에 추가 된 출력 스레드 만 데이터에 액세스하고 있는지 확인하십시오.

출력 스레드는 서로 다른 스레드의 마지막 메시지를 저장하고 해당 데이터를 사용하여 stdout을 올바르게 형식화 할 수 있습니다. 이것은 출력을 지우는 것과 같은 것을 표시하는 것을 포함 할 수 있고, 각 쓰레드가 새로운 데이터를 생성 할 때 그것을 업데이트 할 수있다. 같은 스레드 데몬을 만드는 등 몇 스레드에 인수를 전달에서 개는뿐만 아니라 안전한 종료를 보장하기 위해 몇 가지 트릭의 내 사용이 있다는 것을

Threads 
#1: 0 
#2: 0 

참고. \r 캐리지 리턴 만 현재 출력 행을 다시 시작하므로 줄 바꿈이 사용되지 않습니다.

import queue, threading 
import time, sys 

q = queue.Queue() 
keepRunning = True 

def loop_output(): 
    thread_outputs = dict() 

    while keepRunning: 
     try: 
      thread_id, data = q.get_nowait() 
      thread_outputs[thread_id] = data 
     except queue.Empty: 
      # because the queue is used to update, there's no need to wait or block. 
      pass 

     pretty_output = "" 
     for thread_id, data in thread_outputs.items(): 
      pretty_output += '({}:{}) '.format(thread_id, str(data)) 

     sys.stdout.write('\r' + pretty_output) 
     sys.stdout.flush() 
     time.sleep(1) 

def loop_count(thread_id, increment): 
    count = 0 
    while keepRunning: 
     msg = (thread_id, count) 
     try: 
      q.put_nowait(msg) 
     except queue.Full: 
      pass 

     count = count + increment 
     time.sleep(.3) 
     pass 
    pass 

if __name__ == '__main__': 
    try: 
     th_out = threading.Thread(target=loop_output) 
     th_out.start() 

     # make sure to use args, not pass arguments directly 
     th0 = threading.Thread(target=loop_count, args=("Thread0", 1)) 
     th0.daemon = True 
     th0.start() 

     th1 = threading.Thread(target=loop_count, args=("Thread1", 3)) 
     th1.daemon = True 
     th1.start() 

    # Keep the main thread alive to wait for KeyboardInterrupt 
    while True: 
     time.sleep(.1) 

    except KeyboardInterrupt: 
     print("Ended by keyboard stroke") 
     keepRunning = False 
     for th in [th0, th1]: 
      th.join() 

예 출력 : 표준 출력으로

(Thread0:110) (Thread1:330) 
+0

나를 위해 몇 가지 코드를 작성할 수 있습니까? – BlackVikingPro

+0

@BlackVikingPro 전체 완료 – Aaron3468

+0

정말 고마워! – BlackVikingPro