I\'ve problem to read from Standard input or pipe in python when the pipe is from a \"open\" (do not know right name) file.
I have as example pipetest.py:
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
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
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()
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
k = 0
try:
while True:
print sys.stdin.readline()
k += 1
except KeyboardInterrupt:
sys.stdout.flush()
pass
print k