Last active
December 24, 2022 00:54
-
-
Save ali1234/7a6899ecc77a67a643de65a919457020 to your computer and use it in GitHub Desktop.
Unbuffered, non-blocking stdin in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fcntl | |
import termios | |
import sys | |
import os | |
import time | |
class NonBlockingInput(object): | |
def __enter__(self): | |
# canonical mode, no echo | |
self.old = termios.tcgetattr(sys.stdin) | |
new = termios.tcgetattr(sys.stdin) | |
new[3] = new[3] & ~(termios.ICANON | termios.ECHO) | |
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, new) | |
# set for non-blocking io | |
self.orig_fl = fcntl.fcntl(sys.stdin, fcntl.F_GETFL) | |
fcntl.fcntl(sys.stdin, fcntl.F_SETFL, self.orig_fl | os.O_NONBLOCK) | |
def __exit__(self, *args): | |
# restore terminal to previous state | |
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old) | |
fcntl.fcntl(sys.stdin, fcntl.F_SETFL, self.orig_fl) | |
with NonBlockingInput(): | |
while True: | |
c = sys.stdin.read(1) | |
print('tick', repr(c)) | |
time.sleep(0.1) |
fcntl.fcntl(sys.stdin, fcntl.F_SETFL, orig_fl | ~ os.O_NONBLOCK)
This should be &
not |
but yes, looks good.
Another way is to just remember the orig_fl
from __enter__
and restore it directly. Untested but shouldn't harm anything. :)
Thank you! I've edit like this, works fine: https://gist.github.com/lomalkin/9aa8f0c426655a252180b13bbe8e82c2#file-input-py
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
After use this in case of print() large text I receive:
It looks fixed if edit
def __exit__
like this, to restore blocking output: