Search code examples
pythonpython-3.xsocketsstdin

Get STDIN before user hits enter key


I'm relatively new to socket programming and stdin / stdout and I need to know if there is a way to take input from STDIN before the user hits enter.

For example, if they type 'F' but don't hit enter, I need to see that 'F'. I need this for a basic chatting app, and I need the user's typing to go to the next line so I can print incoming messages without breaking their text.

I've tried freezing STDOUT until the user is done typing, but this just freezes the minute the code reaches the input code block.

Current code:

### Main Handle ###
def Handler():
    print("\nConnected.\n")
    print(f"{server.recv(1028).decode()}\n")
    def _send():
        while True:
            sys.stdout = buffer = io.StringIO()
            text = input()
            sys.stdout = old_stdout
            print(buffer.getvalue())
            try:
                server.sendall(text.encode())
            except:
                pass

    def _get():
        while True:
            print(stdin)
            try:
                message = server.recv(1028).decode()
                if message == "":
                    print("\nYou got disconnected from the server, sorry bud. :C")
                    break
            except ConnectionResetError:
                print("\nYou got disconnected from the server, sorry bud. :C")
                break
            print(f"\n{message}")

    _gthread = Thread(target = _get)
    _gthread.start()
    _sthread = Thread(target = _send)
    _sthread.start()
    while True:
        pass

Any help at all is greatly appreciated. :)


Solution

  • The shell or the terminal emulator, or both, would ask, as part of their startup sequence, to put the terminal into "cooked" mode, which buffers input until it sees a new line. This buffering happens in the terminal driver, before it even reaches your program, which is why your program won't see individual characters in stdin.

    You need to have your program put the terminal into it's raw (uncooked) mode, or a variation of raw mode that doesn't do buffering.

    Python example.

    Note that in the "real" raw mode, CTRL+C and friends don't work, so you probably don't want tty.setraw() but rather tty.setcbreak().