def nonblocking_readlines(f):
"""Generator which yields lines from F (a file object, used only for
its fileno()) without blocking. If there is no data, you get an
endless stream of empty strings until there is data again (caller
is expected to sleep for a while).
Newlines are normalized to the Unix standard.
"""
fd = f.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
enc = locale.getpreferredencoding(False)
buf = bytearray()
while True:
try:
block = os.read(fd, 8192)
except BlockingIOError:
yield ""
continue
if not block:
if buf:
yield buf.decode(enc)
buf.clear()
break
buf.extend(block)
while True:
r = buf.find(b'\r')
n = buf.find(b'\n')
if r == -1 and n == -1: break
if r == -1 or r > n:
yield buf[:(n+1)].decode(enc)
buf = buf[(n+1):]
elif n == -1 or n > r:
yield buf[:r].decode(enc) + '\n'
if n == r+1:
buf = buf[(r+2):]
else:
buf = buf[(r+1):]