If a program exits before all of its input has been consumed, then the remaining input will be sent to the shell.
Here's an example:
import sys
for line in sys.stdin:
sys.exit()
Try running the example and copy-paste this multi-line input:
foo
bar
baz
The result will look like this:
❯ python example.py
foo
bar
baz%
❯ bar
zsh: command not found: bar
❯ baz
In this case, the program exited after consuming foo
, so bar
was automatically sent to the shell. How can I clear the remaining input before Python exits?
The for
loop in the example represents complicated logic, so I'm looking for a solution that doesn't modify the for
loop.
I tried registering an atexit
handler to clear the input:
import sys, atexit
def clear_stdin():
sys.stdin.read()
atexit.register(clear_stdin)
for line in sys.stdin:
sys.exit()
This solution does clear the input and prevent it from being sent to the shell, but it unfortunately causes the program to hang until the user enters a blank line. I'd like to clear the remaining input without pausing the program.
On Unix systems you can use os.set_blocking before reading the input.
If the user pastes a large amount of text, then the terminal may be holding on to additional input that hasn't been sent to stdin yet. It may not be possible for the program to see this, so the following code includes a sleep
to allow for the terminal to provide more input. This code also includes several guards to prevent errors:
import sys, atexit, os
from time import sleep
def clear_stdin():
if sys.__stdin__ and sys.__stdin__.isatty() and hasattr(os, 'set_blocking'):
try:
os.set_blocking(sys.__stdin__.fileno(), False)
except OSError:
return
try:
while sys.__stdin__.read():
sleep(0.1)
except TypeError:
return
atexit.register(clear_stdin)
for line in sys.stdin:
sys.exit()
This will prevent the remaining input from being sent to the shell while still allowing the program to exit immediately:
❯ python example.py
foo
bar
baz%
❯ baz
If the last line does not end with a newline character then it won't be consumed, but it won't be executed by the shell either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With