복붙노트

[PYTHON] 결말이없는 파이프에서 어떻게 파이썬으로 stdin을 읽는가?

PYTHON

결말이없는 파이프에서 어떻게 파이썬으로 stdin을 읽는가?

파이프가 "열린"(올바른 이름을 모르는 경우)에서 표준 입력 또는 파이프를 파이썬으로 읽는 데 문제가 있습니다. 파일.

나는 예제를 가지고있다. pipetest.py :

import sys
import time
k = 0
try:
   for line in sys.stdin:
      k = k + 1
      print line
except KeyboardInterrupt:
   sys.stdout.flush()
   pass
print k

나는 계속 출력을하고 Ctrl + c를 누른 후에 프로그램을 실행한다.

$ ping 127.0.0.1 | python pipetest.py
^C0

출력이 없습니다. 하지만 일반 파일을 통해 가면 작동합니다.

$ ping 127.0.0.1 > testfile.txt

잠시 후 Ctrl + c로 끝납니다.

$ cat testfile.txt |  python pipetest.py

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.017 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.015 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.014 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.013 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.012 ms

--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.012/0.014/0.017/0.003 ms
10

프로그램 종료 전에 출력을 얻으려면 어떻게합니까?이 경우 ping이 종료 되었습니까?

해결법

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

    1.다음 시도 :

    다음 시도 :

    import sys
    import time
    k = 0
    try:
        buff = ''
        while True:
            buff += sys.stdin.read(1)
            if buff.endswith('\n'):
                print buff[:-1]
                buff = ''
                k = k + 1
    except KeyboardInterrupt:
       sys.stdout.flush()
       pass
    print k
    
  2. ==============================

    2.

    k = 0
    try:
        while True:
            print sys.stdin.readline()
            k += 1
    except KeyboardInterrupt:
        sys.stdout.flush()
        pass
    print k
    
  3. ==============================

    3.표준 스트림이 끝날 때까지 기다리지 않고이 작업을 수행하려면 readline에서 반복 할 수 있습니다. 나는 이것이 가장 간단한 해결책이라고 생각한다.

    표준 스트림이 끝날 때까지 기다리지 않고이 작업을 수행하려면 readline에서 반복 할 수 있습니다. 나는 이것이 가장 간단한 해결책이라고 생각한다.

    import sys
    k = 0
    try:
       for line in iter(sys.stdin.readline, b''):
          k = k + 1
          print line
    except KeyboardInterrupt:
       sys.stdout.flush()
       pass
    print k
    
  4. ==============================

    4.sys.stdin은 파일과 유사한 객체입니다. 즉, 줄을 반복 할 수 있음을 의미합니다. 즉, EOF가 삽입 될 때까지 차단됩니다.

    sys.stdin은 파일과 유사한 객체입니다. 즉, 줄을 반복 할 수 있음을 의미합니다. 즉, EOF가 삽입 될 때까지 차단됩니다.

    이 동작은 다음 의사 코드로 설명 할 수 있습니다.

    while True:
        input = ""
        c = stdin.read(1)
        while c is not EOF:
            input += c
            c = stdin.read(1)
        for line in input.split('\n'):
            yield line
    

    즉, sys.stdin의 행을 반복 할 수는 있지만이 작업은 현재 작업에 사용할 수 없으므로 명시 적으로 read () 또는 readline ()을 호출해야합니다.

  5. ==============================

    5.이것이 제가이 일을 끝내는 방법입니다. 나는 다른 해결책을 정말로 좋아하지 않았고, 그들은 매우 비단처럼 보이지 않았습니다.

    이것이 제가이 일을 끝내는 방법입니다. 나는 다른 해결책을 정말로 좋아하지 않았고, 그들은 매우 비단처럼 보이지 않았습니다.

    이렇게하면 열려있는 모든 파일 입력에 대한 컨테이너가 모든 행에서 반복됩니다. 또한 컨텍스트 관리자의 끝에서 파일을 닫는 작업도 처리합니다.

    아마도 sys.stdin : block의 for 행이 기본적으로 어떻게 작동해야하는지 느낍니다.

    class FileInput(object):                                                        
        def __init__(self, file):                                                   
            self.file = file                                                       
    
        def __enter__(self):                                                        
            return self                                                             
    
        def __exit__(self, *args, **kwargs):                                        
            self.file.close()                                                       
    
        def __iter__(self):                                                         
            return self                                                             
    
        def next(self):                                                             
            line = self.file.readline()                                             
    
            if line == None or line == "":                                          
                raise StopIteration                                                 
    
            return line  
    
    with FileInput(sys.stdin) as f:
        for line in f:
            print f
    
    with FileInput(open('tmpfile') as f:
        for line in f:
            print f
    

    명령 줄에서 다음 두 가지 모두 작동합니다.

    tail -f /var/log/debug.log | python fileinput.py
    cat /var/log/debug.log | python fileinput.py
    
  6. from https://stackoverflow.com/questions/7091413/how-do-you-read-from-stdin-in-python-from-a-pipe-which-has-no-ending by cc-by-sa and MIT license