gevent.StreamServer and non-blocking raw_input()?
gevent, python
Solution
The simplest way I've found to do this is to use `gevent.socket.wait_read` to wait until `sys.stdin` can be read:
wait_read(sys.stdin.fileno())
return sys.stdin.readline()
I've also written a small wrapper around file descriptors to give them non-blocking `.read()` and `.write()` methods: https://gist.github.com/2915875
Problem
I've written a simple tcp server using `gevent.StreamServer` for testing purposes. In order for me to send responses to some of the clients, I need a non-blocking way to handle input via `raw_input()`, preferrably without using threads. After some googling I stumbled across this question: How to make non-blocking raw_input when using eventlet.monkey_patch() and why it block everything, even when executed on another thread? I've written the following and it does exactly what I want however I assume there's better approach to it. Could someone point me to the right direction? Also, an idea why the try/except does not catch the KeyboardInterrupt is appreciated. ``` import select from gevent.monkey import patch_all from gevent.server import StreamServer patch_all(os=True, select=True) def raw_input(message): """ Non-blocking input from stdin. """ sys.stdout.write(message) select.select([sys.stdin], [], []) return sys.stdin.readline() def main(): """ Run the server, listen for commands """ server = StreamServer(("0.0.0.0", 6000), handle) print "Starting server" gevent.signal(signal.SIGTERM, server.close) gevent.signal(signal.SIGQUIT, server.close) gevent.signal(signal.SIGINT, server.close) server.start() while True: try: a = raw_input("") if a: print "Received %s" % a gevent.sleep(0) except KeyboardInterrupt: print "Received a shutdown signal, going down ..." server.stop() sys.exit(0) if __name__ == "__main__": main() ``` EDIT: I've rewritten parts of the code and I now understand the silliness of the main()-function. I'll post it as an edit in case someone stumbles on this question and has a better idea on how to do it. ``` from gevent.signal import signal def get_console_input(): """ Non-blocking console input to the server """ select.select([sys.stdin], [], []) # There's quite a bit of code here but it is input handling so # for shortness's sake I've snipped everything and return the line read. return sys.stdin.readline() def exit(server): """ Quit the server gracefully """ print "Received shutdown signal, going down. """ server.close() sys.exit(0) def main(): """ The main function. Create and run the server, listen for commands and append any command to the server so it can send them on to the clients """ # Myserver is a class which inherits from gevent.server.StreamServer. # Myserver could just as well be replaced by gevent.server.StreamServer. server = MyServer(("0.0.0.0", PORT)) print "Starting server" # Add some signal handlers to quit the server gracefully. gevent.signal(signal.SIGTERM, exit, server) gevent.signal(signal.SIGQUIT, exit, server) gevent.signal(signal.SIGINT, exit, server) # Server started in async mode server.start() while True: get_console_input() gevent.sleep(0) if __name__ == "__main__": main() ```