My program (a "TRAC Processor" ) uses character input. I implement readline input functions for lines that end with characters other than enter (usually ' ) and can themselves be multi-line. In this way, I output the escape sequences between the input characters, including the escape sequences that the terminal emulator requests (cursor position and screen size). To make cross-platform single-character input, I used http://code.activestate.com/recipes/134892/ , which was very useful.
This worked great with paste ... until I needed to get a terminal response after the first character of the paste. It seemed that the inserted text was mixed with the response to the escape sequence. I thought I would fix it by flushing the input buffer before initiating an escape sequence request: wait 10 ms, and if the input will not be entered; if there is an input, buffer it and wait again until the input is entered. Based on this post , I tried to poll stdin using select() . Great idea, but it didnโt work, and it produced a very strange behavior. I posted this strange behavior in the original version of this question, believing that I chose a misunderstanding and there was a way to fix it. It seems not, but I found another way to dump (and save) the input stream. I decided to leave this question and post this method as an answer.
The problem with select() is explained here. After the first character of the paste, the other characters are already buffered, and select returns only a new input when there is a new input outside of what is already buffered. I could not force myself to remove the MWE that I generated from this behavior, so you can see it below.
Unfortunately, the answers suggested in this post either do not work for me, or require much more explanation. @slowdog suggests using unbuffered input (os.read (stdin.fileno (), 1) instead of stdin.read (1)). This solves the selection problem, but it breaks the paste: it seems that all the paste characters after the first are buffered regardless of the fact that you never see them. It also did not work with escape sequence responses, which also seem to be buffered. It is also annoying because you need to clear the output buffer, but it is not so scary. @Omnafarious, in a comment, said: "Although, thereโs another way to deal with the Python buffering problem, just to do a parameterless reading, which should read all currently available." This, ultimately, is what I did as follows, but "just" is not so simple. There is another solution here , but I decided there should be a way to do this without streaming.
By the way, there is a relatively simple workaround, because it turns out that the paste does not accidentally alternate with the response to the escape sequence. The rest of the paste is read before the escape sequence response, so when you look for the escape sequence answer (which starts with the escape itself), you can simply buffer all the characters that you read before exiting and process them later. This is only a failure if you can enter ESC characters on the terminal. In any case, at this point I was very busy solving this problem, and I thought that others might find the answer valuable.
In any case, FWIW here is my MWE for the select problem, which simply drives away the text rather than buffering it:
def flush(): import sys, tty, termios from select import select tty.setraw(sys.stdin.fileno()) while True: rlist, wlist, xlist = select([sys.stdin], [], [], 1) if rlist == []: return sys.stdout.write(sys.stdin.read(1))
Paste this into the Python prompt (2.7.9) and put another blank line at the end. If you call flush() and enter text faster than one letter per second, it returns it to you. For example, I typed "hello" and then paused and got this result:
>>> flush() hello>>>
In the OSX Terminal application (at least), if you copy the word text to the clipboard, call the function and press paste for one second, this is what you get:
>>> flush() t>>>
Odd! Only the first letter. Try again without typing:
>>> flush() >>>
He paused for a second and did nothing, like there is no wait input, right? Please try again and click ? :
>>> flush() ext?>>>
Will you get the rest of the pasta saved until ? ! Also, oddly enough, is there a 1 second pause before she dials ? which I do not understand. If you try again at this point, it will behave as usual.
OK, try again by first inserting text , then inserting WTF , then typing ! :
>>> flush() t>>> flush() extW>>> flush() TF!>>>
Thus, the paste only gives the first letter and holds the rest in the input buffer and stops for a second until W and ! . Another weird thing: buffered characters are not entered at the Python >>> prompt.
One lingering question: why do you get an extra 1 second pause before repeating the next letter? The choice does not always wait for the entire period of time ...