Non-blocking stdin with python using epoll

I was playing with epoll and was curious whether I can use it to monitor sys.stdin. The biggest issue was that sys.stdin.read() is blocking and I had no way to figure out whether I read the descriptor fully or not (making the epoll useless pretty much). Until I changed it to non-blocking with fcntl.

import os
import sys
import fcntl
import select

fd = sys.stdin.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

epoll = select.epoll()
epoll.register(fd, select.EPOLLIN)

try:
    while True:
        events = epoll.poll(1)
        for fileno, event in events:
            data = ""
            while True:
                l = sys.stdin.read(64)
                if not l:
                    break
                data += l
            print(data.upper(), end="")

finally:
    epoll.unregister(fd)
    epoll.close()

Sample usage:

$ python3 cat.py
asdqwe
ASDQWE
zxcasd
ZXCASD
^CTraceback (most recent call last):
  File "cat.py", line 15, in <module>
    events = epoll.poll(1)
KeyboardInterrupt
comments powered by Disqus