How do you read from stdin in python from a pipe which has no ending

此生再无相见时 提交于 2019-11-28 06:24:09

Try the next:

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

For this to work without waiting until the stdin stream ends, you can iter on the readline. I think this is the simplest solution.

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
k = 0
try:
    while True:
        print sys.stdin.readline()
        k += 1
except KeyboardInterrupt:
    sys.stdout.flush()
    pass
print k

while sys.stdin is a file-like object, meaning you can iterate over its lines, it will block until a EOF is inserted.

The behaviour can be described with the following pseudo-code:

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

this means that, while you can iterate over sys.stdin's lines, you cannot use this approach for the task at hand and you must explicitly call read() or readline()

This is how I ended up doing this. I didn't really like any of the other solutions, they didn't seem very pythonic.

This will make a container for any open file input to iterate over all the lines. This will also take care of closing the file at the end of the context manager.

I feel like this is probably how the for line in sys.stdin: block should operate by default.

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

From the command line both of the following should work:

tail -f /var/log/debug.log | python fileinput.py
cat /var/log/debug.log | python fileinput.py
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!