I need to read the key pressed by user without waiting for enter.
I want to read both the characters and arrow keys.
The solution that I'm using is the same of this topic.
import sys,tty,termios
def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(3)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
while(1):
k=getch()
if k=='\x1b[A':
print "up"
elif k=='\x1b[B':
print "down"
elif k=='\x1b[C':
print "right"
elif k=='\x1b[D':
print "left"
If I want to read arrow keys I use ch = sys.stdin.read(3), and if I want to read individual characters I use ch = sys.stdin.read(1), but I need to read both types of keys.
The rest of the script is written in Python 2.7 and will run on a Linux system.
Because I'm not the system admistrator, please
don't suggest installing a new package.
Related
I am wanting to make a program with different responses when you press a key. Is there any way that you can detect a key press in Python?
The program is like when you press 0, it will say you pressed 0 and when you pressed ctrl-c it will say that you interrupted the program, so on.
Can you do this in a while True: loop as well?
Also, I don't want it to be like input and I am using Linux (I don't want to have to use root).
Assuming you want a command line application
you should be able to do it with
import sys
import termios
import tty
custom_messages = {'a': 'some other message'}
custom_messages['b'] = 'what?';
stdin = sys.stdin.fileno()
tattr = termios.tcgetattr(stdin)
try:
tty.setcbreak(stdin, termios.TCSANOW)
while True:
char = sys.stdin.read(1)
print(custom_messages.get(char, 'You pressed ' + char))
except KeyboardInterrupt:
print('You interrupted')
sys.exit() ## ?
finally:
termios.tcsetattr(stdin, termios.TCSANOW, tattr)
I based my answer on disabling buffering in stdin
I have a very weird print() bug while using Threads and Termios. I have a repeating Thread catching a key via Termios while printing some stuff. But always it prints a new line it doesn't start at the beginning of the line but where the last line ended.
This is my code:
def func1():
while True:
try:
var = int(inputChar())
except ValueError:
var = 0
Thread(target=func1).start()
while True:
print("stuff")
time.sleep(2)
This is my inputChar() function:
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
This ist the expected output:
stuff
stuff
stuff
stuff
stuff
This is the output:
stuff
stuff
stuff
stuff
stuff
I have no idea why this is happening but you can fix it by replacing the print command with
print("stuff\r")
or
sys.stdout.write("stuff\n\r")
the \r at the end is known as a cartridge return. It's useful when sys.stdout.write() is not a viable option
Currently I am working on a keylogger as final project for my Python course. My idea is that when a user presses the return/enter button the time appears next to the previous typed text. Additionally, I would also like to stop the running when ESC is pressed. This is what I exactly mean:
www.gmail.com 02:20:50
www.google.com 02:21:42
stackoverflow 02:21:44
My code so far is something like this:
import sys, termios, tty, os
from datetime import datetime
def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd , termios.TCSADRAIN , old_settings)
return ch
file=open('register.txt','a')
while True:
char = getch()
if (char != "q"):
file.write(char)
if (char == "\n"):
file.write('\t'+datetime.now().strftime('%H:%M:%S'))
else:
print("Quit!")
exit(0)
file.close()
The problems here are although everything is successfully written in the file register.txt the time doesn't show up, and also I do not have any idea how to specify the character ESC to exit the program
Thanks in advance!
I have been trying to write a keyboard listener without installing any packages. What I wanted was to create a non-blocking way of reading only one character of user input. So I created another thread besides the main one. Here is my code:
import sys, os
import thread
import time
try:
from msvcrt import getch
except ImportError:
def getch():
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
char = None;
def key_listener():
global char;
while True:
char = getch()
# escape key to exit
if ord(char) == 27:
break
#print char #comment this line for test
thread.start_new_thread(key_listener, ())
while True:
print("Whatever")
time.sleep(1);
And the printed strings are a bit weird:
Yinans-MacBook-Pro:anaconda game Yinan$ python inputtest.py
Whatever
Whatever
Whatever
Whatever
Whatever
Whatever
See those indents? I never expected to have that. And I have been trying a whole afternoon to solve it but failed. Does anybody know how to solve this? I will be so grateful. (btw I'm using a macbook pro.)
Putting STDIN in raw mode put STDOUT in raw mode as well, so the normal \n is not expanded to a CRLF. You will need to print a \r at the end of your string in order to return the cursor to the first column.
I'm using Pycharm on unix. I'm trying to read a single character (like 'y' or 'n') from the console. It runs fine, when I execute it on the command line, but when I'm running the program inside Pycharm I get the following error:
termios.error: (25, 'Inappropriate ioctl for device')
I know, that the ide is not a tty, but I haven't found a workaround.
This is my function (seems to be pretty standard) to read the character.
def getch():
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
while True:
char = getch()
if char == 'q':
exit()
else:
print char