복붙노트

[PYTHON] 파이썬에서 다른 쓰레드가 덮어 쓰지 않고 raw_input ()에서 입력 값을 읽음

PYTHON

파이썬에서 다른 쓰레드가 덮어 쓰지 않고 raw_input ()에서 입력 값을 읽음

내가 사용자가 콘솔에서 raw_input ()을 사용하여 명령을 입력 할 수 있도록 노력하고있어,이 잘 작동합니다. 문제는 배경 정보 스레드가 때때로 화면에 로그 정보를 출력하는 것과 그들이 입력 프롬프트를 엉망으로 만들 때입니다. 왜냐하면 출력이 커서가 그 순간에 어디로 가든지간에 갈 수 있기 때문입니다.

이것은 내가 의미하는 것을 보여주는 작은 파이썬 프로그램입니다.

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

def message_loop():
    while True:
        time.sleep(1)
        print "Hello World"

thread = threading.Thread(target = message_loop)
thread.start()

while True:
    input = raw_input("Prompt> ")
    print "You typed", input

다음과 같이 실행했을 때의 모습을 보여줍니다.

Prompt> Hello World
Hello World
Hello World
Hello World
test
You typed test
Prompt> Hello World
Hello World
Hello World
hellHello World
o
You typed hello
Prompt> Hello World
Hello World
Hello World
Hello World

내가 원하는 것은 스레드의 출력과 함께 이동하라는 메시지입니다. 이렇게 :

Hello World
Hello World
Prompt> test
You typed test
Hello World
Hello World
Hello World
Hello World
Hello World
Prompt> hello
You typed hello
Hello World
Hello World
Hello World
Hello World
Prompt> 

못생긴 해킹에 의존하지 않고이를 달성하는 방법에 대한 아이디어가 있습니까? :)

해결법

  1. ==============================

    1.최근에이 문제가 발생하여 나중에 참조 할 수 있도록이 솔루션을 여기에두고 싶습니다. 이 솔루션은 터미널에서 보류중인 raw_input (readline) 텍스트를 지우고 새로운 텍스트를 인쇄 한 다음 raw_input 버퍼에 있던 내용을 터미널에 다시 인쇄합니다.

    최근에이 문제가 발생하여 나중에 참조 할 수 있도록이 솔루션을 여기에두고 싶습니다. 이 솔루션은 터미널에서 보류중인 raw_input (readline) 텍스트를 지우고 새로운 텍스트를 인쇄 한 다음 raw_input 버퍼에 있던 내용을 터미널에 다시 인쇄합니다.

    이 첫 번째 프로그램은 매우 단순하지만 raw_input을 기다리는 텍스트가 한 줄 밖에 없을 때만 올바르게 작동합니다.

    #!/usr/bin/python
    
    import time,readline,thread,sys
    
    def noisy_thread():
        while True:
            time.sleep(3)
            sys.stdout.write('\r'+' '*(len(readline.get_line_buffer())+2)+'\r')
            print 'Interrupting text!'
            sys.stdout.write('> ' + readline.get_line_buffer())
            sys.stdout.flush()
    
    thread.start_new_thread(noisy_thread, ())
    while True:
        s = raw_input('> ')
    

    산출:

    $ ./threads_input.py
    Interrupting text!
    Interrupting text!
    Interrupting text!
    > WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
    Interrupting text!
    > WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
    naparte family. No, I warn you, that if you do not tell me we are at war,
    

    두 번째는 2 개 이상의 버퍼 라인을 올바르게 처리하지만 더 많은 (표준적인) 모듈 의존성을 가지며 약간의 터미널 해커가 필요합니다.

    #!/usr/bin/python
    
    import time,readline,thread
    import sys,struct,fcntl,termios
    
    def blank_current_readline():
        # Next line said to be reasonably portable for various Unixes
        (rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))
    
        text_len = len(readline.get_line_buffer())+2
    
        # ANSI escape sequences (All VT100 except ESC[0G)
        sys.stdout.write('\x1b[2K')                         # Clear current line
        sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols))  # Move cursor up and clear line
        sys.stdout.write('\x1b[0G')                         # Move to start of line
    
    
    def noisy_thread():
        while True:
            time.sleep(3)
            blank_current_readline()
            print 'Interrupting text!'
            sys.stdout.write('> ' + readline.get_line_buffer())
            sys.stdout.flush()          # Needed or text doesn't show until a key is pressed
    
    
    if __name__ == '__main__':
        thread.start_new_thread(noisy_thread, ())
        while True:
            s = raw_input('> ')
    

    산출. 이전 readline 행이 제대로 지워졌습니다.

    $ ./threads_input2.py
    Interrupting text!
    Interrupting text!
    Interrupting text!
    Interrupting text!
    > WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
    naparte family. No, I warn you, that if you do not tell me we are at war,
    

    유용한 출처 :

    파이썬에서 리눅스 콘솔 창 너비를 얻는 방법

    apt 같은 열 출력 - 파이썬 라이브러리 (이 코드 샘플은 Unix 또는 Windows 용 터미널 폭을 얻는 방법을 보여줍니다)

    http://en.wikipedia.org/wiki/ANSI_escape_code

  2. ==============================

    2.터미널 창에서 텍스트를 동적으로 인쇄 / 삭제 / 덮어 쓸 수있는 기능이 필요하다고 생각합니다. UNIX watch 또는 top 명령의 작동 방식.

    터미널 창에서 텍스트를 동적으로 인쇄 / 삭제 / 덮어 쓸 수있는 기능이 필요하다고 생각합니다. UNIX watch 또는 top 명령의 작동 방식.

    귀하의 경우 "프롬프트>"를 인쇄 할 것이라고 생각하지만 "Hello World"를 얻으면 "프롬프트">를 "Hello World"로 덮어 쓰고 아래 줄에 "프롬프트>"를 인쇄하십시오. 나는 당신이 터미널에 정기적 인 출력 인쇄를 할 수 있다고 생각하지 않는다.

    파이썬의 curses 라이브러리를 사용하여 원하는 것을 할 수있다. 나는 문제를 해결할 수있는 방법을 말할 수 없으므로 (또는 모듈이 문제를 해결할 수있을지라도) 사용하지는 못했지만, 살펴볼 가치가 있다고 생각합니다. "파이썬 저주 튜토리얼"을 검색하면 도움이되는 PDF 튜토리얼 문서가 제공됩니다.

  3. ==============================

    3.다중 스레드가 아닌 단일 스레드에서 stdout을 갱신해야합니다. 그렇지 않으면 인터리브 된 I / O를 제어 할 수 없습니다.

    다중 스레드가 아닌 단일 스레드에서 stdout을 갱신해야합니다. 그렇지 않으면 인터리브 된 I / O를 제어 할 수 없습니다.

    출력 쓰기를위한 단일 스레드를 작성하려고합니다.

    스레드의 대기열을 사용하고 다른 모든 스레드가 출력 로깅 정보를 쓰도록 할 수 있습니다. 그런 다음이 대기열에서 읽고 프롬프트 메시지와 함께 적절한 시간에 stdout에 기록하십시오.

  4. ==============================

    4.나는 그것이 가능하다고 생각하지 않는다. 어떻게해야합니까? 사용자가 Enter 키를 누를 때까지 아무 것도 표시되지 않습니까? 그렇다면 사용자가 명령을 내릴 때 (또는 시스템이 예상하는대로) 출력이 오게되는데, 이는 바람직하지 않은 것입니다.

    나는 그것이 가능하다고 생각하지 않는다. 어떻게해야합니까? 사용자가 Enter 키를 누를 때까지 아무 것도 표시되지 않습니까? 그렇다면 사용자가 명령을 내릴 때 (또는 시스템이 예상하는대로) 출력이 오게되는데, 이는 바람직하지 않은 것입니다.

    스레드가 다른 파일로 출력해야합니다.

  5. from https://stackoverflow.com/questions/2082387/reading-input-from-raw-input-without-having-the-prompt-overwritten-by-other-th by cc-by-sa and MIT license