You can use the selector to multiplex I / O for input:
https://docs.python.org/3/library/selectors.html
Try the following:
#! /usr/bin/python3 import sys import fcntl import os import selectors
The above code will contain a string
for k, mask in m_selector.select():
until a registered event occurs, returning an instance of selector_key (k) and a mask of monitored events.
In the above example, we registered only one event (press Enter):
m_selector.register(sys.stdin, selectors.EVENT_READ, got_keyboard_data)
An instance of a selection key is defined as follows:
abstractmethod register(fileobj, events, data=None)
Therefore, the register method sets k.data as the got_keyboard_data callback function and calls it when you press Enter:
callback = k.data callback(k.fileobj)
A more complete example (and hopefully more useful) would be multiplexing stdin data from a user using network connections:
import selectors import socket import sys import os import fcntl m_selector = selectors.DefaultSelector() # set sys.stdin non-blocking def set_input_nonblocking(): orig_fl = fcntl.fcntl(sys.stdin, fcntl.F_GETFL) fcntl.fcntl(sys.stdin, fcntl.F_SETFL, orig_fl | os.O_NONBLOCK) def create_socket(port, max_conn): server_addr = ('localhost', port) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.setblocking(False) server.bind(server_addr) server.listen(max_conn) return server def read(conn, mask): global GO_ON client_address = conn.getpeername() data = conn.recv(1024) print('Got {} from {}'.format(data, client_address)) if not data: GO_ON = False def accept(sock, mask): new_conn, addr = sock.accept() new_conn.setblocking(False) print('Accepting connection from {}'.format(addr)) m_selector.register(new_conn, selectors.EVENT_READ, read) def quit(): global GO_ON print('Exiting...') GO_ON = False def from_keyboard(arg1, arg2): line = arg1.read() if line == 'quit\n': quit() else: print('User input: {}'.format(line)) GO_ON = True set_input_nonblocking() # listen to port 10000, at most 10 connections server = create_socket(10000, 10) m_selector.register(server, selectors.EVENT_READ, accept) m_selector.register(sys.stdin, selectors.EVENT_READ, from_keyboard) while GO_ON: sys.stdout.write('>>> ') sys.stdout.flush() for k, mask in m_selector.select(): callback = k.data callback(k.fileobj, mask) # unregister events m_selector.unregister(sys.stdin) # close connection server.shutdown() server.close() # close select m_selector.close()
You can test using two terminals. first terminal:
$ python3 test.py >>> bla
open another terminal and run:
$ nc localhost 10000 hey!
back to the first
>>> qwerqwer
Result (displayed on the main terminal):
$ python3 test.py >>> bla User input: bla >>> Accepting connection from ('127.0.0.1', 39598) >>> Got b'hey!\n' from ('127.0.0.1', 39598) >>> qwerqwer User input: qwerqwer >>>