Avatar of amillyard
amillyard
Flag for United Kingdom of Great Britain and Northern Ireland asked on

capture key press

Using Python3 (console mode).

I am trying to capture key press (restrict to certain digits and charaters) - non-allows characters presses not displayed otherwise see a text string appear on screen.

New to Python -- advise much appreciated
import msvcrt        

def doKeyEvent(key):
    if key == '\x00' or key == '\xe0':    # non ASCII
       key = msvcrt.getch()
    print (ord(key),)

def doQuitEvent(key):
    raise SystemExit


def keyTest1() :


    ky = msvcrt.getch()
    length = len(ky)
    if length != 0:         
        if ky == " ":
            doQuitEvent(ky)
        else: 
            doKeyEvent(ky)

Open in new window

Python

Avatar of undefined
Last Comment
pepr

8/22/2022 - Mon
pepr

Try the following snippet to see, what is returned.  Now, the important thing is to understand that there is a strict difference between strings and bytes in Python3.  The msvcrt.getch() returns the bytes type (literals having b in front of the first quotation mark).  This way, you have to convert the bytes explicitly to get the string.  Strings in Python3 are always in Unicode.  This also means that you have to tell the encoding for the conversion.

I do recommend to read the Strings chapter (http://diveintopython3.org/strings.html) from Dive Into Python 3 by Mark Pilgrim (http://diveintopython3.org/), namely the section Strings vs. Bytes (http://diveintopython3.org/strings.html#byte-arrays).
import msvcrt        

k = None          # init
while k != b' ':  # press space to leave the loop
    k = msvcrt.getch()
    print(repr(k))

Open in new window

amillyard

ASKER
thanks for the feedback.

when I apply the above scripting... the   b'\xff'  constantly streams upwards.

what I am hoping to achieve is text entry on a single line ... any non-allowed character  (from a list eventually) simply does not get added to the input (ignored).

at the moment I cannot break unless using Ctrl-C



b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
b'\xff'
Traceback (most recent call last):
  File "C:\Users\Administrator\Desktop\ass1.py", line 357, in <module>
    elif len(line)==1 and "1"<=line<="9" : exlist[int(line)]()
  File "C:\Users\Administrator\Desktop\ass1.py", line 248, in ex8
    print(repr(k))
KeyboardInterrupt
>>> 
pepr

Can you show your code from around the line 248 in ass1.py?
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
pepr

... and around 357
amillyard

ASKER
there are basically just a bunch of functions ... the break was the ctrl-c to force the stop... otherwise -the scripting loops on itself (the above scripting)
pepr

I am just curious where the b'\xff' came from.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
amillyard

ASKER
this is the only scripting in that section - a loop to select different functions to test various routines as attached
# do not modify anything beneath this line
exlist = [None, ex1, ex2, ex3, ex4, ex5, ex6, ex7, ex8, ex9]
running = True
while running :
    line = input("\nSelect option (0 to quit): ")
    if line == "0" : running = False
    elif line == "10" : ex10()
    elif len(line)==1 and "1"<=line<="9" : exlist[int(line)]()
    else : print("Invalid input - try again")

Open in new window

pepr

I am afraid you cannot combine the standard input() function and the msvcrt.getch() together.  I may be wrong but you need to write your own implementation of the input() -- say myInput().  Try the code below to discuss about.  It uses getch() to get the characters of the keys and collects them in the list of single-char strings.  However, it is rather simplistic as it works only with ASCII characters.  Try to press the arrow key or some accented character and you will know what I mean.  On the other hand, there are places in the code where the tests could be added to solve the situations.
import msvcrt        

k = None      # init
lst = []
while k != b'\r':
    k = msvcrt.getch()
    if k != b'\r':
       msvcrt.putch(k)
       lst.append(k.decode('ascii'))

msvcrt.putch(b'\n') 
    
print(repr(''.join(lst)))

Open in new window

ASKER CERTIFIED SOLUTION
pepr

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.